diff --git a/[refs] b/[refs] index 643d1d2c1744..8f92ce0c762e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ce6cac88a4f1e52a51a31c31562f4da347543147 +refs/heads/master: 828d7d7b19446bf5a40928da47955c575a454c75 diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 05ed6f301d89..274b32d12532 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -35,6 +35,17 @@ Who: Luis R. Rodriguez --------------------------- +What: AR9170USB +When: 2.6.40 + +Why: This driver is deprecated and the firmware is no longer + maintained. The replacement driver "carl9170" has been + around for a while, so the devices are still supported. + +Who: Christian Lamparter + +--------------------------- + What: IRQF_SAMPLE_RANDOM Check: IRQF_SAMPLE_RANDOM When: July 2009 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 9f9104987a73..6b4b9cdec370 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1224,6 +1224,13 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k S: Supported F: drivers/net/wireless/ath/ath9k/ +ATHEROS AR9170 WIRELESS DRIVER +M: Christian Lamparter +L: linux-wireless@vger.kernel.org +W: http://wireless.kernel.org/en/users/Drivers/ar9170 +S: Obsolete +F: drivers/net/wireless/ath/ar9170/ + CARL9170 LINUX COMMUNITY WIRELESS DRIVER M: Christian Lamparter L: linux-wireless@vger.kernel.org @@ -3348,12 +3355,6 @@ F: Documentation/wimax/README.i2400m F: drivers/net/wimax/i2400m/ F: include/linux/wimax/i2400m.h -INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy) -M: Stanislaw Gruszka -L: linux-wireless@vger.kernel.org -S: Supported -F: drivers/net/wireless/iwlegacy/ - INTEL WIRELESS WIFI LINK (iwlwifi) M: Wey-Yi Guy M: Intel Linux Wireless diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index f354bd4e121e..7aeb113cbb90 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -284,6 +284,5 @@ source "drivers/net/wireless/rtlwifi/Kconfig" source "drivers/net/wireless/wl1251/Kconfig" source "drivers/net/wireless/wl12xx/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" -source "drivers/net/wireless/mwifiex/Kconfig" endif # WLAN diff --git a/trunk/drivers/net/wireless/Makefile b/trunk/drivers/net/wireless/Makefile index 7bba6a82b875..ddd3fb6ba1d3 100644 --- a/trunk/drivers/net/wireless/Makefile +++ b/trunk/drivers/net/wireless/Makefile @@ -56,5 +56,3 @@ obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/ obj-$(CONFIG_IWM) += iwmc3200wifi/ - -obj-$(CONFIG_MWIFIEX) += mwifiex/ diff --git a/trunk/drivers/net/wireless/ath/Kconfig b/trunk/drivers/net/wireless/ath/Kconfig index d1b23067619f..92c216263ee9 100644 --- a/trunk/drivers/net/wireless/ath/Kconfig +++ b/trunk/drivers/net/wireless/ath/Kconfig @@ -24,6 +24,7 @@ config ATH_DEBUG source "drivers/net/wireless/ath/ath5k/Kconfig" source "drivers/net/wireless/ath/ath9k/Kconfig" +source "drivers/net/wireless/ath/ar9170/Kconfig" source "drivers/net/wireless/ath/carl9170/Kconfig" endif diff --git a/trunk/drivers/net/wireless/ath/Makefile b/trunk/drivers/net/wireless/ath/Makefile index 0e8f528c81c0..6d711ec97ec2 100644 --- a/trunk/drivers/net/wireless/ath/Makefile +++ b/trunk/drivers/net/wireless/ath/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH9K_HW) += ath9k/ +obj-$(CONFIG_AR9170_USB) += ar9170/ obj-$(CONFIG_CARL9170) += carl9170/ obj-$(CONFIG_ATH_COMMON) += ath.o diff --git a/trunk/drivers/net/wireless/ath/ar9170/Kconfig b/trunk/drivers/net/wireless/ath/ar9170/Kconfig new file mode 100644 index 000000000000..7b9672b0d090 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/Kconfig @@ -0,0 +1,20 @@ +config AR9170_USB + tristate "Atheros AR9170 802.11n USB support (OBSOLETE)" + depends on USB && MAC80211 + select FW_LOADER + help + This driver is going to get replaced by carl9170. + + This is a driver for the Atheros "otus" 802.11n USB devices. + + These devices require additional firmware (2 files). + For now, these files can be downloaded from here: + + http://wireless.kernel.org/en/users/Drivers/ar9170 + + If you choose to build a module, it'll be called ar9170usb. + +config AR9170_LEDS + bool + depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) + default y diff --git a/trunk/drivers/net/wireless/ath/ar9170/Makefile b/trunk/drivers/net/wireless/ath/ar9170/Makefile new file mode 100644 index 000000000000..8d91c7ee3215 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/Makefile @@ -0,0 +1,3 @@ +ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o + +obj-$(CONFIG_AR9170_USB) += ar9170usb.o diff --git a/trunk/drivers/net/wireless/ath/ar9170/ar9170.h b/trunk/drivers/net/wireless/ath/ar9170/ar9170.h new file mode 100644 index 000000000000..371e4ce49528 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/ar9170.h @@ -0,0 +1,258 @@ +/* + * Atheros AR9170 driver + * + * Driver specific definitions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AR9170_H +#define __AR9170_H + +#include +#include +#include +#include +#ifdef CONFIG_AR9170_LEDS +#include +#endif /* CONFIG_AR9170_LEDS */ +#include "eeprom.h" +#include "hw.h" + +#include "../regd.h" + +#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) + +enum ar9170_bw { + AR9170_BW_20, + AR9170_BW_40_BELOW, + AR9170_BW_40_ABOVE, + + __AR9170_NUM_BW, +}; + +static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) +{ + switch (type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + return AR9170_BW_20; + case NL80211_CHAN_HT40MINUS: + return AR9170_BW_40_BELOW; + case NL80211_CHAN_HT40PLUS: + return AR9170_BW_40_ABOVE; + default: + BUG(); + } +} + +enum ar9170_rf_init_mode { + AR9170_RFI_NONE, + AR9170_RFI_WARM, + AR9170_RFI_COLD, +}; + +#define AR9170_MAX_RX_BUFFER_SIZE 8192 + +#ifdef CONFIG_AR9170_LEDS +struct ar9170; + +struct ar9170_led { + struct ar9170 *ar; + struct led_classdev l; + char name[32]; + unsigned int toggled; + bool last_state; + bool registered; +}; + +#endif /* CONFIG_AR9170_LEDS */ + +enum ar9170_device_state { + AR9170_UNKNOWN_STATE, + AR9170_STOPPED, + AR9170_IDLE, + AR9170_STARTED, +}; + +struct ar9170_rxstream_mpdu_merge { + struct ar9170_rx_head plcp; + bool has_plcp; +}; + +struct ar9170_tx_queue_stats { + unsigned int len; + unsigned int limit; + unsigned int count; +}; + +#define AR9170_QUEUE_TIMEOUT 64 +#define AR9170_TX_TIMEOUT 8 +#define AR9170_JANITOR_DELAY 128 +#define AR9170_TX_INVALID_RATE 0xffffffff + +#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH +#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) + +struct ar9170 { + struct ieee80211_hw *hw; + struct ath_common common; + struct mutex mutex; + enum ar9170_device_state state; + bool registered; + unsigned long bad_hw_nagger; + + int (*open)(struct ar9170 *); + void (*stop)(struct ar9170 *); + int (*tx)(struct ar9170 *, struct sk_buff *); + int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , + void *, u32 , void *); + void (*callback_cmd)(struct ar9170 *, u32 , void *); + int (*flush)(struct ar9170 *); + + /* interface mode settings */ + struct ieee80211_vif *vif; + + /* beaconing */ + struct sk_buff *beacon; + struct work_struct beacon_work; + bool enable_beacon; + + /* cryptographic engine */ + u64 usedkeys; + bool rx_software_decryption; + bool disable_offload; + + /* filter settings */ + u64 cur_mc_hash; + u32 cur_filter; + unsigned int filter_state; + bool sniffer_enabled; + + /* PHY */ + struct ieee80211_channel *channel; + int noise[4]; + + /* power calibration data */ + u8 power_5G_leg[4]; + u8 power_2G_cck[4]; + u8 power_2G_ofdm[4]; + u8 power_5G_ht20[8]; + u8 power_5G_ht40[8]; + u8 power_2G_ht20[8]; + u8 power_2G_ht40[8]; + + u8 phy_heavy_clip; + +#ifdef CONFIG_AR9170_LEDS + struct delayed_work led_work; + struct ar9170_led leds[AR9170_NUM_LEDS]; +#endif /* CONFIG_AR9170_LEDS */ + + /* qos queue settings */ + spinlock_t tx_stats_lock; + struct ar9170_tx_queue_stats tx_stats[5]; + struct ieee80211_tx_queue_params edcf[5]; + + spinlock_t cmdlock; + __le32 cmdbuf[PAYLOAD_MAX + 1]; + + /* MAC statistics */ + struct ieee80211_low_level_stats stats; + + /* EEPROM */ + struct ar9170_eeprom eeprom; + + /* tx queues - as seen by hw - */ + struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; + struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; + struct delayed_work tx_janitor; + + /* rxstream mpdu merge */ + struct ar9170_rxstream_mpdu_merge rx_mpdu; + struct sk_buff *rx_failover; + int rx_failover_missing; + + /* (cached) HW A-MPDU settings */ + u8 global_ampdu_density; + u8 global_ampdu_factor; +}; + +struct ar9170_tx_info { + unsigned long timeout; +}; + +#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) +#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) + +/* exported interface */ +void *ar9170_alloc(size_t priv_size); +int ar9170_register(struct ar9170 *ar, struct device *pdev); +void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); +void ar9170_unregister(struct ar9170 *ar); +void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); +void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); +int ar9170_nag_limiter(struct ar9170 *ar); + +/* MAC */ +void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +int ar9170_init_mac(struct ar9170 *ar); +int ar9170_set_qos(struct ar9170 *ar); +int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); +int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); +int ar9170_set_operating_mode(struct ar9170 *ar); +int ar9170_set_beacon_timers(struct ar9170 *ar); +int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); +int ar9170_set_slot_time(struct ar9170 *ar); +int ar9170_set_basic_rates(struct ar9170 *ar); +int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); +int ar9170_update_beacon(struct ar9170 *ar); +void ar9170_new_beacon(struct work_struct *work); +int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, + u8 keyidx, u8 *keydata, int keylen); +int ar9170_disable_key(struct ar9170 *ar, u8 id); + +/* LEDs */ +#ifdef CONFIG_AR9170_LEDS +int ar9170_register_leds(struct ar9170 *ar); +void ar9170_unregister_leds(struct ar9170 *ar); +#endif /* CONFIG_AR9170_LEDS */ +int ar9170_init_leds(struct ar9170 *ar); +int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); + +/* PHY / RF */ +int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); +int ar9170_init_rf(struct ar9170 *ar); +int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, + enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); + +#endif /* __AR9170_H */ diff --git a/trunk/drivers/net/wireless/ath/ar9170/cmd.c b/trunk/drivers/net/wireless/ath/ar9170/cmd.c new file mode 100644 index 000000000000..6452c5055a63 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/cmd.c @@ -0,0 +1,127 @@ +/* + * Atheros AR9170 driver + * + * Basic HW register/memory/command access functions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ar9170.h" +#include "cmd.h" + +int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) +{ + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); + if (err) + wiphy_debug(ar->hw->wiphy, "writing memory failed\n"); + return err; +} + +int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) +{ + const __le32 buf[2] = { + cpu_to_le32(reg), + cpu_to_le32(val), + }; + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), + (u8 *) buf, 0, NULL); + if (err) + wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n", + reg, val); + return err; +} + +int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out) +{ + int i, err; + __le32 *offs, *res; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + /* abuse "out" for the register offsets, must be same length */ + offs = (__le32 *)out; + for (i = 0; i < nregs; i++) + offs[i] = cpu_to_le32(regs[i]); + + /* also use the same buffer for the input */ + res = (__le32 *)out; + + err = ar->exec_cmd(ar, AR9170_CMD_RREG, + 4 * nregs, (u8 *)offs, + 4 * nregs, (u8 *)res); + if (err) + return err; + + /* convert result to cpu endian */ + for (i = 0; i < nregs; i++) + out[i] = le32_to_cpu(res[i]); + + return 0; +} + +int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) +{ + return ar9170_read_mreg(ar, 1, ®, val); +} + +int ar9170_echo_test(struct ar9170 *ar, u32 v) +{ + __le32 echobuf = cpu_to_le32(v); + __le32 echores; + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return -ENODEV; + + err = ar->exec_cmd(ar, AR9170_CMD_ECHO, + 4, (u8 *)&echobuf, + 4, (u8 *)&echores); + if (err) + return err; + + if (echobuf != echores) + return -EINVAL; + + return 0; +} diff --git a/trunk/drivers/net/wireless/ath/ar9170/cmd.h b/trunk/drivers/net/wireless/ath/ar9170/cmd.h new file mode 100644 index 000000000000..ec8134b4b949 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/cmd.h @@ -0,0 +1,92 @@ +/* + * Atheros AR9170 driver + * + * Basic HW register/memory/command access functions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __CMD_H +#define __CMD_H + +#include "ar9170.h" + +/* basic HW access */ +int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); +int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); +int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); +int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out); +int ar9170_echo_test(struct ar9170 *ar, u32 v); + +/* + * Macros to facilitate writing multiple registers in a single + * write-combining USB command. Note that when the first group + * fails the whole thing will fail without any others attempted, + * but you won't know which write in the group failed. + */ +#define ar9170_regwrite_begin(ar) \ +do { \ + int __nreg = 0, __err = 0; \ + struct ar9170 *__ar = ar; + +#define ar9170_regwrite(r, v) do { \ + __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ + __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ + __nreg++; \ + if ((__nreg >= PAYLOAD_MAX/2)) { \ + if (IS_ACCEPTING_CMD(__ar)) \ + __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ + 8 * __nreg, \ + (u8 *) &__ar->cmdbuf[1], \ + 0, NULL); \ + __nreg = 0; \ + if (__err) \ + goto __regwrite_out; \ + } \ +} while (0) + +#define ar9170_regwrite_finish() \ +__regwrite_out : \ + if (__nreg) { \ + if (IS_ACCEPTING_CMD(__ar)) \ + __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ + 8 * __nreg, \ + (u8 *) &__ar->cmdbuf[1], \ + 0, NULL); \ + __nreg = 0; \ + } + +#define ar9170_regwrite_result() \ + __err; \ +} while (0); + +#endif /* __CMD_H */ diff --git a/trunk/drivers/net/wireless/ath/ar9170/eeprom.h b/trunk/drivers/net/wireless/ath/ar9170/eeprom.h new file mode 100644 index 000000000000..6c4663883423 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/eeprom.h @@ -0,0 +1,179 @@ +/* + * Atheros AR9170 driver + * + * EEPROM layout + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AR9170_EEPROM_H +#define __AR9170_EEPROM_H + +#define AR5416_MAX_CHAINS 2 +#define AR5416_MODAL_SPURS 5 + +struct ar9170_eeprom_modal { + __le32 antCtrlChain[AR5416_MAX_CHAINS]; + __le32 antCtrlCommon; + s8 antennaGainCh[AR5416_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR5416_MAX_CHAINS]; + u8 rxTxMarginCh[AR5416_MAX_CHAINS]; + s8 adcDesiredSize; + s8 pgaDesiredSize; + u8 xlnaGainCh[AR5416_MAX_CHAINS]; + u8 txEndToXpaOff; + u8 txEndToRxOn; + u8 txFrameToXpaOn; + u8 thresh62; + s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; + u8 xpdGain; + u8 xpd; + s8 iqCalICh[AR5416_MAX_CHAINS]; + s8 iqCalQCh[AR5416_MAX_CHAINS]; + u8 pdGainOverlap; + u8 ob; + u8 db; + u8 xpaBiasLvl; + u8 pwrDecreaseFor2Chain; + u8 pwrDecreaseFor3Chain; + u8 txFrameToDataStart; + u8 txFrameToPaOn; + u8 ht40PowerIncForPdadc; + u8 bswAtten[AR5416_MAX_CHAINS]; + u8 bswMargin[AR5416_MAX_CHAINS]; + u8 swSettleHt40; + u8 reserved[22]; + struct spur_channel { + __le16 spurChan; + u8 spurRangeLow; + u8 spurRangeHigh; + } __packed spur_channels[AR5416_MODAL_SPURS]; +} __packed; + +#define AR5416_NUM_PD_GAINS 4 +#define AR5416_PD_GAIN_ICEPTS 5 + +struct ar9170_calibration_data_per_freq { + u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; +} __packed; + +#define AR5416_NUM_5G_CAL_PIERS 8 +#define AR5416_NUM_2G_CAL_PIERS 4 + +#define AR5416_NUM_5G_TARGET_PWRS 8 +#define AR5416_NUM_2G_CCK_TARGET_PWRS 3 +#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 +#define AR5416_MAX_NUM_TGT_PWRS 8 + +struct ar9170_calibration_target_power_legacy { + u8 freq; + u8 power[4]; +} __packed; + +struct ar9170_calibration_target_power_ht { + u8 freq; + u8 power[8]; +} __packed; + +#define AR5416_NUM_CTLS 24 + +struct ar9170_calctl_edges { + u8 channel; +#define AR9170_CALCTL_EDGE_FLAGS 0xC0 + u8 power_flags; +} __packed; + +#define AR5416_NUM_BAND_EDGES 8 + +struct ar9170_calctl_data { + struct ar9170_calctl_edges + control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; +} __packed; + + +struct ar9170_eeprom { + __le16 length; + __le16 checksum; + __le16 version; + u8 operating_flags; +#define AR9170_OPFLAG_5GHZ 1 +#define AR9170_OPFLAG_2GHZ 2 + u8 misc; + __le16 reg_domain[2]; + u8 mac_address[6]; + u8 rx_mask; + u8 tx_mask; + __le16 rf_silent; + __le16 bluetooth_options; + __le16 device_capabilities; + __le32 build_number; + u8 deviceType; + u8 reserved[33]; + + u8 customer_data[64]; + + struct ar9170_eeprom_modal + modal_header[2]; + + u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; + u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; + + struct ar9170_calibration_data_per_freq + cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], + cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; + + /* power calibration data */ + struct ar9170_calibration_target_power_legacy + cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; + struct ar9170_calibration_target_power_ht + cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], + cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; + + struct ar9170_calibration_target_power_legacy + cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], + cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; + struct ar9170_calibration_target_power_ht + cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], + cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; + + /* conformance testing limits */ + u8 ctl_index[AR5416_NUM_CTLS]; + struct ar9170_calctl_data + ctl_data[AR5416_NUM_CTLS]; + + u8 pad; + __le16 subsystem_id; +} __packed; + +#endif /* __AR9170_EEPROM_H */ diff --git a/trunk/drivers/net/wireless/ath/ar9170/hw.h b/trunk/drivers/net/wireless/ath/ar9170/hw.h new file mode 100644 index 000000000000..06f1f3c951a4 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/hw.h @@ -0,0 +1,430 @@ +/* + * Atheros AR9170 driver + * + * Hardware-specific definitions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AR9170_HW_H +#define __AR9170_HW_H + +#define AR9170_MAX_CMD_LEN 64 + +enum ar9170_cmd { + AR9170_CMD_RREG = 0x00, + AR9170_CMD_WREG = 0x01, + AR9170_CMD_RMEM = 0x02, + AR9170_CMD_WMEM = 0x03, + AR9170_CMD_BITAND = 0x04, + AR9170_CMD_BITOR = 0x05, + AR9170_CMD_EKEY = 0x28, + AR9170_CMD_DKEY = 0x29, + AR9170_CMD_FREQUENCY = 0x30, + AR9170_CMD_RF_INIT = 0x31, + AR9170_CMD_SYNTH = 0x32, + AR9170_CMD_FREQ_START = 0x33, + AR9170_CMD_ECHO = 0x80, + AR9170_CMD_TALLY = 0x81, + AR9170_CMD_TALLY_APD = 0x82, + AR9170_CMD_CONFIG = 0x83, + AR9170_CMD_RESET = 0x90, + AR9170_CMD_DKRESET = 0x91, + AR9170_CMD_DKTX_STATUS = 0x92, + AR9170_CMD_FDC = 0xA0, + AR9170_CMD_WREEPROM = 0xB0, + AR9170_CMD_WFLASH = 0xB0, + AR9170_CMD_FLASH_ERASE = 0xB1, + AR9170_CMD_FLASH_PROG = 0xB2, + AR9170_CMD_FLASH_CHKSUM = 0xB3, + AR9170_CMD_FLASH_READ = 0xB4, + AR9170_CMD_FW_DL_INIT = 0xB5, + AR9170_CMD_MEM_WREEPROM = 0xBB, +}; + +/* endpoints */ +#define AR9170_EP_TX 1 +#define AR9170_EP_RX 2 +#define AR9170_EP_IRQ 3 +#define AR9170_EP_CMD 4 + +#define AR9170_EEPROM_START 0x1600 + +#define AR9170_GPIO_REG_BASE 0x1d0100 +#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE +#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) +#define AR9170_NUM_LEDS 2 + + +#define AR9170_USB_REG_BASE 0x1e1000 +#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) +#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 +#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 +#define AR9170_DMA_CTL_HIGH_SPEED 0x4 +#define AR9170_DMA_CTL_PACKET_MODE 0x8 + +#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) +#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) + + + +#define AR9170_MAC_REG_BASE 0x1c3000 + +#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) +#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) + +#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C) +#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) +#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) + +#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) +#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) +#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) +#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) + +#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) +#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) + +#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C) + +#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) +#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) +#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) +#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) +#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) +#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C) + +#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) +#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) +#define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0) +#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 +#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) +#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) +#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 + +#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) +#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) + +#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) +#define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0) +#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) +#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) +#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) +#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) +#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) +#define AR9170_MAC_REG_FTF_BIT6 BIT(6) +#define AR9170_MAC_REG_FTF_BIT7 BIT(7) +#define AR9170_MAC_REG_FTF_BEACON BIT(8) +#define AR9170_MAC_REG_FTF_ATIM BIT(9) +#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) +#define AR9170_MAC_REG_FTF_AUTH BIT(11) +#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) +#define AR9170_MAC_REG_FTF_BIT13 BIT(13) +#define AR9170_MAC_REG_FTF_BIT14 BIT(14) +#define AR9170_MAC_REG_FTF_BIT15 BIT(15) +#define AR9170_MAC_REG_FTF_BAR BIT(24) +#define AR9170_MAC_REG_FTF_BA BIT(25) +#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) +#define AR9170_MAC_REG_FTF_RTS BIT(27) +#define AR9170_MAC_REG_FTF_CTS BIT(28) +#define AR9170_MAC_REG_FTF_ACK BIT(29) +#define AR9170_MAC_REG_FTF_CFE BIT(30) +#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) +#define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff +#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff + +#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) +#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4) +#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8) +#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC) +#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0) +#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC) +#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC) +#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) + + +#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) +#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) + +#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) + +#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) +#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 +#define AR9170_MAC_REG_POWERMGT_AP 0xa1 +#define AR9170_MAC_REG_POWERMGT_STA 0x2 +#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 +#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) + +#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) +#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) + +#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00) +#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04) +#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08) +#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C) +#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10) +#define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) +#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) + +#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) + +#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0) +#define AR9170_MAC_FCS_SWFCS 0x1 +#define AR9170_MAC_FCS_FIFO_PROT 0x4 + + +#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) + +#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) +#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) + +#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C) +#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0) + +#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) +#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) + +#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C) +#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f +#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 +#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 +#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 + +#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84) +#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88) +#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) +#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) +#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) +#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) + + +#define AR9170_PWR_REG_BASE 0x1D4000 + +#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) +#define AR9170_PWR_CLK_AHB_40MHZ 0 +#define AR9170_PWR_CLK_AHB_20_22MHZ 1 +#define AR9170_PWR_CLK_AHB_40_44MHZ 2 +#define AR9170_PWR_CLK_AHB_80_88MHZ 3 +#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 + + +/* put beacon here in memory */ +#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 + + +struct ar9170_tx_control { + __le16 length; + __le16 mac_control; + __le32 phy_control; + u8 frame_data[0]; +} __packed; + +/* these are either-or */ +#define AR9170_TX_MAC_PROT_RTS 0x0001 +#define AR9170_TX_MAC_PROT_CTS 0x0002 + +#define AR9170_TX_MAC_NO_ACK 0x0004 +/* if unset, MAC will only do SIFS space before frame */ +#define AR9170_TX_MAC_BACKOFF 0x0008 +#define AR9170_TX_MAC_BURST 0x0010 +#define AR9170_TX_MAC_AGGR 0x0020 + +/* encryption is a two-bit field */ +#define AR9170_TX_MAC_ENCR_NONE 0x0000 +#define AR9170_TX_MAC_ENCR_RC4 0x0040 +#define AR9170_TX_MAC_ENCR_CENC 0x0080 +#define AR9170_TX_MAC_ENCR_AES 0x00c0 + +#define AR9170_TX_MAC_MMIC 0x0100 +#define AR9170_TX_MAC_HW_DURATION 0x0200 +#define AR9170_TX_MAC_QOS_SHIFT 10 +#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) +#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 +#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 +#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 +#define AR9170_TX_MAC_TXOP_RIFS 0x2000 +#define AR9170_TX_MAC_IMM_AMPDU 0x4000 +#define AR9170_TX_MAC_RATE_PROBE 0x8000 + +/* either-or */ +#define AR9170_TX_PHY_MOD_MASK 0x00000003 +#define AR9170_TX_PHY_MOD_CCK 0x00000000 +#define AR9170_TX_PHY_MOD_OFDM 0x00000001 +#define AR9170_TX_PHY_MOD_HT 0x00000002 + +/* depends on modulation */ +#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 +#define AR9170_TX_PHY_GREENFIELD 0x00000004 + +#define AR9170_TX_PHY_BW_SHIFT 3 +#define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT) +#define AR9170_TX_PHY_BW_20MHZ 0 +#define AR9170_TX_PHY_BW_40MHZ 2 +#define AR9170_TX_PHY_BW_40MHZ_DUP 3 + +#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 +#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) + +#define AR9170_TX_PHY_TX_PWR_SHIFT 9 +#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) + +/* not part of the hw-spec */ +#define AR9170_TX_PHY_QOS_SHIFT 25 +#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) + +#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 +#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) +#define AR9170_TX_PHY_TXCHAIN_1 1 +/* use for cck, ofdm 6/9/12/18/24 and HT if capable */ +#define AR9170_TX_PHY_TXCHAIN_2 5 + +#define AR9170_TX_PHY_MCS_SHIFT 18 +#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) + +#define AR9170_TX_PHY_SHORT_GI 0x80000000 + +#define AR5416_MAX_RATE_POWER 63 + +struct ar9170_rx_head { + u8 plcp[12]; +} __packed; + +struct ar9170_rx_phystatus { + union { + struct { + u8 rssi_ant0, rssi_ant1, rssi_ant2, + rssi_ant0x, rssi_ant1x, rssi_ant2x, + rssi_combined; + } __packed; + u8 rssi[7]; + } __packed; + + u8 evm_stream0[6], evm_stream1[6]; + u8 phy_err; +} __packed; + +struct ar9170_rx_macstatus { + u8 SAidx, DAidx; + u8 error; + u8 status; +} __packed; + +#define AR9170_ENC_ALG_NONE 0x0 +#define AR9170_ENC_ALG_WEP64 0x1 +#define AR9170_ENC_ALG_TKIP 0x2 +#define AR9170_ENC_ALG_AESCCMP 0x4 +#define AR9170_ENC_ALG_WEP128 0x5 +#define AR9170_ENC_ALG_WEP256 0x6 +#define AR9170_ENC_ALG_CENC 0x7 + +#define AR9170_RX_ENC_SOFTWARE 0x8 + +static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) +{ + return (t->SAidx & 0xc0) >> 4 | + (t->DAidx & 0xc0) >> 6; +} + +#define AR9170_RX_STATUS_MODULATION_MASK 0x03 +#define AR9170_RX_STATUS_MODULATION_CCK 0x00 +#define AR9170_RX_STATUS_MODULATION_OFDM 0x01 +#define AR9170_RX_STATUS_MODULATION_HT 0x02 +#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 + +/* depends on modulation */ +#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 +#define AR9170_RX_STATUS_GREENFIELD 0x08 + +#define AR9170_RX_STATUS_MPDU_MASK 0x30 +#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 +#define AR9170_RX_STATUS_MPDU_FIRST 0x20 +#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 +#define AR9170_RX_STATUS_MPDU_LAST 0x10 + +#define AR9170_RX_ERROR_RXTO 0x01 +#define AR9170_RX_ERROR_OVERRUN 0x02 +#define AR9170_RX_ERROR_DECRYPT 0x04 +#define AR9170_RX_ERROR_FCS 0x08 +#define AR9170_RX_ERROR_WRONG_RA 0x10 +#define AR9170_RX_ERROR_PLCP 0x20 +#define AR9170_RX_ERROR_MMIC 0x40 +#define AR9170_RX_ERROR_FATAL 0x80 + +struct ar9170_cmd_tx_status { + u8 dst[ETH_ALEN]; + __le32 rate; + __le16 status; +} __packed; + +#define AR9170_TX_STATUS_COMPLETE 0x00 +#define AR9170_TX_STATUS_RETRY 0x01 +#define AR9170_TX_STATUS_FAILED 0x02 + +struct ar9170_cmd_ba_failed_count { + __le16 failed; + __le16 rate; +} __packed; + +struct ar9170_cmd_response { + u8 flag; + u8 type; + __le16 padding; + + union { + struct ar9170_cmd_tx_status tx_status; + struct ar9170_cmd_ba_failed_count ba_fail_cnt; + u8 data[0]; + }; +} __packed; + +/* QoS */ + +/* mac80211 queue to HW/FW map */ +static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; + +/* HW/FW queue to mac80211 map */ +static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; + +enum ar9170_txq { + AR9170_TXQ_BE, + AR9170_TXQ_BK, + AR9170_TXQ_VI, + AR9170_TXQ_VO, + + __AR9170_NUM_TXQ, +}; + +#define AR9170_TXQ_DEPTH 32 +#define AR9170_TX_MAX_PENDING 128 +#define AR9170_RX_STREAM_MAX_SIZE 65535 + +#endif /* __AR9170_HW_H */ diff --git a/trunk/drivers/net/wireless/ath/ar9170/led.c b/trunk/drivers/net/wireless/ath/ar9170/led.c new file mode 100644 index 000000000000..832d90087f8a --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/led.c @@ -0,0 +1,181 @@ +/* + * Atheros AR9170 driver + * + * LED handling + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ar9170.h" +#include "cmd.h" + +int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) +{ + return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); +} + +int ar9170_init_leds(struct ar9170 *ar) +{ + int err; + + /* disable LEDs */ + /* GPIO [0/1 mode: output, 2/3: input] */ + err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); + if (err) + goto out; + + /* GPIO 0/1 value: off */ + err = ar9170_set_leds_state(ar, 0); + +out: + return err; +} + +#ifdef CONFIG_AR9170_LEDS +static void ar9170_update_leds(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); + int i, tmp, blink_delay = 1000; + u32 led_val = 0; + bool rerun = false; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return ; + + mutex_lock(&ar->mutex); + for (i = 0; i < AR9170_NUM_LEDS; i++) + if (ar->leds[i].registered && ar->leds[i].toggled) { + led_val |= 1 << i; + + tmp = 70 + 200 / (ar->leds[i].toggled); + if (tmp < blink_delay) + blink_delay = tmp; + + if (ar->leds[i].toggled > 1) + ar->leds[i].toggled = 0; + + rerun = true; + } + + ar9170_set_leds_state(ar, led_val); + mutex_unlock(&ar->mutex); + + if (!rerun) + return; + + ieee80211_queue_delayed_work(ar->hw, + &ar->led_work, + msecs_to_jiffies(blink_delay)); +} + +static void ar9170_led_brightness_set(struct led_classdev *led, + enum led_brightness brightness) +{ + struct ar9170_led *arl = container_of(led, struct ar9170_led, l); + struct ar9170 *ar = arl->ar; + + if (unlikely(!arl->registered)) + return ; + + if (arl->last_state != !!brightness) { + arl->toggled++; + arl->last_state = !!brightness; + } + + if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) + ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); +} + +static int ar9170_register_led(struct ar9170 *ar, int i, char *name, + char *trigger) +{ + int err; + + snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), + "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name); + + ar->leds[i].ar = ar; + ar->leds[i].l.name = ar->leds[i].name; + ar->leds[i].l.brightness_set = ar9170_led_brightness_set; + ar->leds[i].l.brightness = 0; + ar->leds[i].l.default_trigger = trigger; + + err = led_classdev_register(wiphy_dev(ar->hw->wiphy), + &ar->leds[i].l); + if (err) + wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", + ar->leds[i].name, err); + else + ar->leds[i].registered = true; + + return err; +} + +void ar9170_unregister_leds(struct ar9170 *ar) +{ + int i; + + for (i = 0; i < AR9170_NUM_LEDS; i++) + if (ar->leds[i].registered) { + led_classdev_unregister(&ar->leds[i].l); + ar->leds[i].registered = false; + ar->leds[i].toggled = 0; + } + + cancel_delayed_work_sync(&ar->led_work); +} + +int ar9170_register_leds(struct ar9170 *ar) +{ + int err; + + INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); + + err = ar9170_register_led(ar, 0, "tx", + ieee80211_get_tx_led_name(ar->hw)); + if (err) + goto fail; + + err = ar9170_register_led(ar, 1, "assoc", + ieee80211_get_assoc_led_name(ar->hw)); + if (err) + goto fail; + + return 0; + +fail: + ar9170_unregister_leds(ar); + return err; +} + +#endif /* CONFIG_AR9170_LEDS */ diff --git a/trunk/drivers/net/wireless/ath/ar9170/mac.c b/trunk/drivers/net/wireless/ath/ar9170/mac.c new file mode 100644 index 000000000000..857e86104295 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/mac.c @@ -0,0 +1,519 @@ +/* + * Atheros AR9170 driver + * + * MAC programming + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ar9170.h" +#include "cmd.h" + +int ar9170_set_dyn_sifs_ack(struct ar9170 *ar) +{ + u32 val; + + if (conf_is_ht40(&ar->hw->conf)) + val = 0x010a; + else { + if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) + val = 0x105; + else + val = 0x104; + } + + return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); +} + +int ar9170_set_slot_time(struct ar9170 *ar) +{ + u32 slottime = 20; + + if (!ar->vif) + return 0; + + if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || + ar->vif->bss_conf.use_short_slot) + slottime = 9; + + return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10); +} + +int ar9170_set_basic_rates(struct ar9170 *ar) +{ + u8 cck, ofdm; + + if (!ar->vif) + return 0; + + ofdm = ar->vif->bss_conf.basic_rates >> 4; + + /* FIXME: is still necessary? */ + if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) + cck = 0; + else + cck = ar->vif->bss_conf.basic_rates & 0xf; + + return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE, + ofdm << 8 | cck); +} + +int ar9170_set_qos(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | + (ar->edcf[0].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | + (ar->edcf[1].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | + (ar->edcf[2].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | + (ar->edcf[3].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | + (ar->edcf[4].cw_max << 16)); + + ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, + ((ar->edcf[0].aifs * 9 + 10)) | + ((ar->edcf[1].aifs * 9 + 10) << 12) | + ((ar->edcf[2].aifs * 9 + 10) << 24)); + ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, + ((ar->edcf[2].aifs * 9 + 10) >> 8) | + ((ar->edcf[3].aifs * 9 + 10) << 4) | + ((ar->edcf[4].aifs * 9 + 10) << 16)); + + ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, + ar->edcf[0].txop | ar->edcf[1].txop << 16); + ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, + ar->edcf[2].txop | ar->edcf[3].txop << 16); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) +{ + u32 val; + + /* don't allow AMPDU density > 8us */ + if (mpdudensity > 6) + return -EINVAL; + + /* Watch out! Otus uses slightly different density values. */ + val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_init_mac(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); + + ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); + + /* enable MMIC */ + ar9170_regwrite(AR9170_MAC_REG_SNIFFER, + AR9170_MAC_REG_SNIFFER_DEFAULTS); + + ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); + + ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); + ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); + ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); + + /* CF-END mode */ + ar9170_regwrite(0x1c3b2c, 0x19000000); + + /* NAV protects ACK only (in TXOP) */ + ar9170_regwrite(0x1c3b38, 0x201); + + /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ + /* OTUS set AM to 0x1 */ + ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); + + ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); + + /* AGG test code*/ + /* Aggregation MAX number and timeout */ + ar9170_regwrite(0x1c3b9c, 0x10000a); + + ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, + AR9170_MAC_REG_FTF_DEFAULTS); + + /* Enable deaggregator, response in sniffer mode */ + ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); + + /* rate sets */ + ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); + ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); + ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); + + /* MIMO response control */ + ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ + + /* switch MAC to OTUS interface */ + ar9170_regwrite(0x1c3600, 0x3); + + ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); + + /* set PHY register read timeout (??) */ + ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); + + /* Disable Rx TimeOut, workaround for BB. */ + ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); + + /* Set CPU clock frequency to 88/80MHz */ + ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, + AR9170_PWR_CLK_AHB_80_88MHZ | + AR9170_PWR_CLK_DAC_160_INV_DLY); + + /* Set WLAN DMA interrupt mode: generate int per packet */ + ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); + + ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, + AR9170_MAC_FCS_FIFO_PROT); + + /* Disables the CF_END frame, undocumented register */ + ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, + 0x141E0F48); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) +{ + static const u8 zero[ETH_ALEN] = { 0 }; + + if (!mac) + mac = zero; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(reg, get_unaligned_le32(mac)); + ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) +{ + int err; + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + ar->cur_mc_hash = mc_hash; + return 0; +} + +int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) +{ + int err; + + err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); + if (err) + return err; + + ar->cur_filter = filter; + return 0; +} + +static int ar9170_set_promiscouous(struct ar9170 *ar) +{ + u32 encr_mode, sniffer; + int err; + + err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); + if (err) + return err; + + err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); + if (err) + return err; + + if (ar->sniffer_enabled) { + sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; + + /* + * Rx decryption works in place. + * + * If we don't disable it, the hardware will render all + * encrypted frames which are encrypted with an unknown + * key useless. + */ + + encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + ar->sniffer_enabled = true; + } else { + sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; + + if (ar->rx_software_decryption) + encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + else + encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); + ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_set_operating_mode(struct ar9170 *ar) +{ + struct ath_common *common = &ar->common; + u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; + u8 *mac_addr, *bssid; + int err; + + if (ar->vif) { + mac_addr = common->macaddr; + bssid = common->curbssid; + + switch (ar->vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; + break; + case NL80211_IFTYPE_AP: + pm_mode |= AR9170_MAC_REG_POWERMGT_AP; + break; + case NL80211_IFTYPE_WDS: + pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; + break; + case NL80211_IFTYPE_MONITOR: + ar->sniffer_enabled = true; + ar->rx_software_decryption = true; + break; + default: + pm_mode |= AR9170_MAC_REG_POWERMGT_STA; + break; + } + } else { + mac_addr = NULL; + bssid = NULL; + } + + err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); + if (err) + return err; + + err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); + if (err) + return err; + + err = ar9170_set_promiscouous(ar); + if (err) + return err; + + /* set AMPDU density to 8us. */ + err = ar9170_set_ampdu_density(ar, 6); + if (err) + return err; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) +{ + u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); + + return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); +} + +int ar9170_set_beacon_timers(struct ar9170 *ar) +{ + u32 v = 0; + u32 pretbtt = 0; + + if (ar->vif) { + v |= ar->vif->bss_conf.beacon_int; + + if (ar->enable_beacon) { + switch (ar->vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + v |= BIT(25); + break; + case NL80211_IFTYPE_AP: + v |= BIT(24); + pretbtt = (ar->vif->bss_conf.beacon_int - 6) << + 16; + break; + default: + break; + } + } + + v |= ar->vif->bss_conf.dtim_period << 16; + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); + ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +int ar9170_update_beacon(struct ar9170 *ar) +{ + struct sk_buff *skb; + __le32 *data, *old = NULL; + u32 word; + int i; + + skb = ieee80211_beacon_get(ar->hw, ar->vif); + if (!skb) + return -ENOMEM; + + data = (__le32 *)skb->data; + if (ar->beacon) + old = (__le32 *)ar->beacon->data; + + ar9170_regwrite_begin(ar); + for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { + /* + * XXX: This accesses beyond skb data for up + * to the last 3 bytes!! + */ + + if (old && (data[i] == old[i])) + continue; + + word = le32_to_cpu(data[i]); + ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); + } + + /* XXX: use skb->cb info */ + if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) + ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, + ((skb->len + 4) << (3 + 16)) + 0x0400); + else + ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, + ((skb->len + 4) << 16) + 0x001b); + + ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); + ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); + ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); + + ar9170_regwrite_finish(); + + dev_kfree_skb(ar->beacon); + ar->beacon = skb; + + return ar9170_regwrite_result(); +} + +void ar9170_new_beacon(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + beacon_work); + struct sk_buff *skb; + + if (unlikely(!IS_STARTED(ar))) + return ; + + mutex_lock(&ar->mutex); + + if (!ar->vif) + goto out; + + ar9170_update_beacon(ar); + + rcu_read_lock(); + while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) + ar9170_op_tx(ar->hw, skb); + + rcu_read_unlock(); + + out: + mutex_unlock(&ar->mutex); +} + +int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, + u8 keyidx, u8 *keydata, int keylen) +{ + __le32 vals[7]; + static const u8 bcast[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + u8 dummy; + + mac = mac ? : bcast; + + vals[0] = cpu_to_le32((keyidx << 16) + id); + vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); + vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | + mac[3] << 8 | mac[2]); + memset(&vals[3], 0, 16); + if (keydata) + memcpy(&vals[3], keydata, keylen); + + return ar->exec_cmd(ar, AR9170_CMD_EKEY, + sizeof(vals), (u8 *)vals, + 1, &dummy); +} + +int ar9170_disable_key(struct ar9170 *ar, u8 id) +{ + __le32 val = cpu_to_le32(id); + u8 dummy; + + return ar->exec_cmd(ar, AR9170_CMD_EKEY, + sizeof(val), (u8 *)&val, + 1, &dummy); +} diff --git a/trunk/drivers/net/wireless/ath/ar9170/main.c b/trunk/drivers/net/wireless/ath/ar9170/main.c new file mode 100644 index 000000000000..b761fec0d721 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/main.c @@ -0,0 +1,2190 @@ +/* + * Atheros AR9170 driver + * + * mac80211 interaction code + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include "ar9170.h" +#include "hw.h" +#include "cmd.h" + +static int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ + .bitrate = (_bitrate), \ + .flags = (_flags), \ + .hw_value = (_hw_rate) | (_txpidx) << 4, \ +} + +static struct ieee80211_rate __ar9170_ratetable[] = { + RATE(10, 0, 0, 0), + RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(60, 0xb, 0, 0), + RATE(90, 0xf, 0, 0), + RATE(120, 0xa, 0, 0), + RATE(180, 0xe, 0, 0), + RATE(240, 0x9, 0, 0), + RATE(360, 0xd, 1, 0), + RATE(480, 0x8, 2, 0), + RATE(540, 0xc, 3, 0), +}; +#undef RATE + +#define ar9170_g_ratetable (__ar9170_ratetable + 0) +#define ar9170_g_ratetable_size 12 +#define ar9170_a_ratetable (__ar9170_ratetable + 4) +#define ar9170_a_ratetable_size 8 + +/* + * NB: The hw_value is used as an index into the ar9170_phy_freq_params + * array in phy.c so that we don't have to do frequency lookups! + */ +#define CHAN(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 18, /* XXX */ \ +} + +static struct ieee80211_channel ar9170_2ghz_chantable[] = { + CHAN(2412, 0), + CHAN(2417, 1), + CHAN(2422, 2), + CHAN(2427, 3), + CHAN(2432, 4), + CHAN(2437, 5), + CHAN(2442, 6), + CHAN(2447, 7), + CHAN(2452, 8), + CHAN(2457, 9), + CHAN(2462, 10), + CHAN(2467, 11), + CHAN(2472, 12), + CHAN(2484, 13), +}; + +static struct ieee80211_channel ar9170_5ghz_chantable[] = { + CHAN(4920, 14), + CHAN(4940, 15), + CHAN(4960, 16), + CHAN(4980, 17), + CHAN(5040, 18), + CHAN(5060, 19), + CHAN(5080, 20), + CHAN(5180, 21), + CHAN(5200, 22), + CHAN(5220, 23), + CHAN(5240, 24), + CHAN(5260, 25), + CHAN(5280, 26), + CHAN(5300, 27), + CHAN(5320, 28), + CHAN(5500, 29), + CHAN(5520, 30), + CHAN(5540, 31), + CHAN(5560, 32), + CHAN(5580, 33), + CHAN(5600, 34), + CHAN(5620, 35), + CHAN(5640, 36), + CHAN(5660, 37), + CHAN(5680, 38), + CHAN(5700, 39), + CHAN(5745, 40), + CHAN(5765, 41), + CHAN(5785, 42), + CHAN(5805, 43), + CHAN(5825, 44), + CHAN(5170, 45), + CHAN(5190, 46), + CHAN(5210, 47), + CHAN(5230, 48), +}; +#undef CHAN + +#define AR9170_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ + IEEE80211_HT_CAP_SGI_40 | \ + IEEE80211_HT_CAP_GRN_FLD | \ + IEEE80211_HT_CAP_DSSSCCK40 | \ + IEEE80211_HT_CAP_SM_PS, \ + .ampdu_factor = 3, \ + .ampdu_density = 6, \ + .mcs = { \ + .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ + .rx_highest = cpu_to_le16(300), \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ + }, \ +} + +static struct ieee80211_supported_band ar9170_band_2GHz = { + .channels = ar9170_2ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), + .bitrates = ar9170_g_ratetable, + .n_bitrates = ar9170_g_ratetable_size, + .ht_cap = AR9170_HT_CAP, +}; + +static struct ieee80211_supported_band ar9170_band_5GHz = { + .channels = ar9170_5ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), + .bitrates = ar9170_a_ratetable, + .n_bitrates = ar9170_a_ratetable_size, + .ht_cap = AR9170_HT_CAP, +}; + +static void ar9170_tx(struct ar9170 *ar); + +static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) +{ + return le16_to_cpu(hdr->seq_ctrl) >> 4; +} + +static inline u16 ar9170_get_seq(struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + return ar9170_get_seq_h((void *) txc->frame_data); +} + +#ifdef AR9170_QUEUE_DEBUG +static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); + struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + + wiphy_debug(ar->hw->wiphy, + "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d " + "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", + skb, skb_get_queue_mapping(skb), + ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), + le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), + jiffies_to_msecs(arinfo->timeout - jiffies)); +} + +static void __ar9170_dump_txqueue(struct ar9170 *ar, + struct sk_buff_head *queue) +{ + struct sk_buff *skb; + int i = 0; + + printk(KERN_DEBUG "---[ cut here ]---\n"); + wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n", + skb_queue_len(queue)); + + skb_queue_walk(queue, skb) { + printk(KERN_DEBUG "index:%d =>\n", i++); + ar9170_print_txheader(ar, skb); + } + if (i != skb_queue_len(queue)) + printk(KERN_DEBUG "WARNING: queue frame counter " + "mismatch %d != %d\n", skb_queue_len(queue), i); + printk(KERN_DEBUG "---[ end ]---\n"); +} +#endif /* AR9170_QUEUE_DEBUG */ + +#ifdef AR9170_QUEUE_DEBUG +static void ar9170_dump_txqueue(struct ar9170 *ar, + struct sk_buff_head *queue) +{ + unsigned long flags; + + spin_lock_irqsave(&queue->lock, flags); + __ar9170_dump_txqueue(ar, queue); + spin_unlock_irqrestore(&queue->lock, flags); +} +#endif /* AR9170_QUEUE_DEBUG */ + +#ifdef AR9170_QUEUE_STOP_DEBUG +static void __ar9170_dump_txstats(struct ar9170 *ar) +{ + int i; + + wiphy_debug(ar->hw->wiphy, "QoS queue stats\n"); + + for (i = 0; i < __AR9170_NUM_TXQ; i++) + wiphy_debug(ar->hw->wiphy, + "queue:%d limit:%d len:%d waitack:%d stopped:%d\n", + i, ar->tx_stats[i].limit, ar->tx_stats[i].len, + skb_queue_len(&ar->tx_status[i]), + ieee80211_queue_stopped(ar->hw, i)); +} +#endif /* AR9170_QUEUE_STOP_DEBUG */ + +/* caller must guarantee exclusive access for _bin_ queue. */ +static void ar9170_recycle_expired(struct ar9170 *ar, + struct sk_buff_head *queue, + struct sk_buff_head *bin) +{ + struct sk_buff *skb, *old = NULL; + unsigned long flags; + + spin_lock_irqsave(&queue->lock, flags); + while ((skb = skb_peek(queue))) { + struct ieee80211_tx_info *txinfo; + struct ar9170_tx_info *arinfo; + + txinfo = IEEE80211_SKB_CB(skb); + arinfo = (void *) txinfo->rate_driver_data; + + if (time_is_before_jiffies(arinfo->timeout)) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "[%ld > %ld] frame expired => recycle\n", + jiffies, arinfo->timeout); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + __skb_unlink(skb, queue); + __skb_queue_tail(bin, skb); + } else { + break; + } + + if (unlikely(old == skb)) { + /* bail out - queue is shot. */ + + WARN_ON(1); + break; + } + old = skb; + } + spin_unlock_irqrestore(&queue->lock, flags); +} + +static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, + u16 tx_status) +{ + struct ieee80211_tx_info *txinfo; + unsigned int retries = 0; + + txinfo = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(txinfo); + + switch (tx_status) { + case AR9170_TX_STATUS_RETRY: + retries = 2; + case AR9170_TX_STATUS_COMPLETE: + txinfo->flags |= IEEE80211_TX_STAT_ACK; + break; + + case AR9170_TX_STATUS_FAILED: + retries = ar->hw->conf.long_frame_max_tx_count; + break; + + default: + wiphy_err(ar->hw->wiphy, + "invalid tx_status response (%x)\n", tx_status); + break; + } + + txinfo->status.rates[0].count = retries + 1; + skb_pull(skb, sizeof(struct ar9170_tx_control)); + ieee80211_tx_status_irqsafe(ar->hw, skb); +} + +void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data; + unsigned int queue = skb_get_queue_mapping(skb); + unsigned long flags; + + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[queue].len--; + + if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { +#ifdef AR9170_QUEUE_STOP_DEBUG + wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ + ieee80211_wake_queue(ar->hw, queue); + } + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) { + ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); + } else { + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); + + skb_queue_tail(&ar->tx_status[queue], skb); + } + + if (!ar->tx_stats[queue].len && + !skb_queue_empty(&ar->tx_pending[queue])) { + ar9170_tx(ar); + } +} + +static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, + const u8 *mac, + struct sk_buff_head *queue, + const u32 rate) +{ + unsigned long flags; + struct sk_buff *skb; + + /* + * Unfortunately, the firmware does not tell to which (queued) frame + * this transmission status report belongs to. + * + * So we have to make risky guesses - with the scarce information + * the firmware provided (-> destination MAC, and phy_control) - + * and hope that we picked the right one... + */ + + spin_lock_irqsave(&queue->lock, flags); + skb_queue_walk(queue, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + u32 r; + + if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "skip frame => DA %pM != %pM\n", + mac, ieee80211_get_DA(hdr)); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + continue; + } + + r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >> + AR9170_TX_PHY_MCS_SHIFT; + + if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "skip frame => rate %d != %d\n", rate, r); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + continue; + } + + __skb_unlink(skb, queue); + spin_unlock_irqrestore(&queue->lock, flags); + return skb; + } + +#ifdef AR9170_QUEUE_DEBUG + wiphy_err(ar->hw->wiphy, + "ESS:[%pM] does not have any outstanding frames in queue.\n", + mac); + __ar9170_dump_txqueue(ar, queue); +#endif /* AR9170_QUEUE_DEBUG */ + spin_unlock_irqrestore(&queue->lock, flags); + + return NULL; +} + +/* + * This worker tries to keeps an maintain tx_status queues. + * So we can guarantee that incoming tx_status reports are + * actually for a pending frame. + */ + +static void ar9170_tx_janitor(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + tx_janitor.work); + struct sk_buff_head waste; + unsigned int i; + bool resched = false; + + if (unlikely(!IS_STARTED(ar))) + return ; + + skb_queue_head_init(&waste); + + for (i = 0; i < __AR9170_NUM_TXQ; i++) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n", + i); + ar9170_dump_txqueue(ar, &ar->tx_pending[i]); + ar9170_dump_txqueue(ar, &ar->tx_status[i]); +#endif /* AR9170_QUEUE_DEBUG */ + + ar9170_recycle_expired(ar, &ar->tx_status[i], &waste); + ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste); + skb_queue_purge(&waste); + + if (!skb_queue_empty(&ar->tx_status[i]) || + !skb_queue_empty(&ar->tx_pending[i])) + resched = true; + } + + if (!resched) + return; + + ieee80211_queue_delayed_work(ar->hw, + &ar->tx_janitor, + msecs_to_jiffies(AR9170_JANITOR_DELAY)); +} + +void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) +{ + struct ar9170_cmd_response *cmd = (void *) buf; + + if ((cmd->type & 0xc0) != 0xc0) { + ar->callback_cmd(ar, len, buf); + return; + } + + /* hardware event handlers */ + switch (cmd->type) { + case 0xc1: { + /* + * TX status notification: + * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 + * + * XX always 81 + * YY always 00 + * M1-M6 is the MAC address + * R1-R4 is the transmit rate + * S1-S2 is the transmit status + */ + + struct sk_buff *skb; + u32 phy = le32_to_cpu(cmd->tx_status.rate); + u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> + AR9170_TX_PHY_QOS_SHIFT; +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "recv tx_status for %pm, p:%08x, q:%d\n", + cmd->tx_status.dst, phy, q); +#endif /* AR9170_QUEUE_DEBUG */ + + skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, + &ar->tx_status[q], + AR9170_TX_INVALID_RATE); + if (unlikely(!skb)) + return ; + + ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status)); + break; + } + + case 0xc0: + /* + * pre-TBTT event + */ + if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) + ieee80211_queue_work(ar->hw, &ar->beacon_work); + break; + + case 0xc2: + /* + * (IBSS) beacon send notification + * bytes: 04 c2 XX YY B4 B3 B2 B1 + * + * XX always 80 + * YY always 00 + * B1-B4 "should" be the number of send out beacons. + */ + break; + + case 0xc3: + /* End of Atim Window */ + break; + + case 0xc4: + /* BlockACK bitmap */ + break; + + case 0xc5: + /* BlockACK events */ + break; + + case 0xc6: + /* Watchdog Interrupt */ + break; + + case 0xc9: + /* retransmission issue / SIFS/EIFS collision ?! */ + break; + + /* firmware debug */ + case 0xca: + printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, + (char *)buf + 4); + break; + case 0xcb: + len -= 4; + + switch (len) { + case 1: + printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n", + *((char *)buf + 4)); + break; + case 2: + printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n", + le16_to_cpup((__le16 *)((char *)buf + 4))); + break; + case 4: + printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n", + le32_to_cpup((__le32 *)((char *)buf + 4))); + break; + case 8: + printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n", + (unsigned long)le64_to_cpup( + (__le64 *)((char *)buf + 4))); + break; + } + break; + case 0xcc: + print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE, + (char *)buf + 4, len - 4); + break; + + default: + pr_info("received unhandled event %x\n", cmd->type); + print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); + break; + } +} + +static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) +{ + memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); + ar->rx_mpdu.has_plcp = false; +} + +int ar9170_nag_limiter(struct ar9170 *ar) +{ + bool print_message; + + /* + * we expect all sorts of errors in promiscuous mode. + * don't bother with it, it's OK! + */ + if (ar->sniffer_enabled) + return false; + + /* + * only go for frequent errors! The hardware tends to + * do some stupid thing once in a while under load, in + * noisy environments or just for fun! + */ + if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) + print_message = true; + else + print_message = false; + + /* reset threshold for "once in a while" */ + ar->bad_hw_nagger = jiffies + HZ / 4; + return print_message; +} + +static int ar9170_rx_mac_status(struct ar9170 *ar, + struct ar9170_rx_head *head, + struct ar9170_rx_macstatus *mac, + struct ieee80211_rx_status *status) +{ + u8 error, decrypt; + + BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); + BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); + + error = mac->error; + if (error & AR9170_RX_ERROR_MMIC) { + status->flag |= RX_FLAG_MMIC_ERROR; + error &= ~AR9170_RX_ERROR_MMIC; + } + + if (error & AR9170_RX_ERROR_PLCP) { + status->flag |= RX_FLAG_FAILED_PLCP_CRC; + error &= ~AR9170_RX_ERROR_PLCP; + + if (!(ar->filter_state & FIF_PLCPFAIL)) + return -EINVAL; + } + + if (error & AR9170_RX_ERROR_FCS) { + status->flag |= RX_FLAG_FAILED_FCS_CRC; + error &= ~AR9170_RX_ERROR_FCS; + + if (!(ar->filter_state & FIF_FCSFAIL)) + return -EINVAL; + } + + decrypt = ar9170_get_decrypt_type(mac); + if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && + decrypt != AR9170_ENC_ALG_NONE) + status->flag |= RX_FLAG_DECRYPTED; + + /* ignore wrong RA errors */ + error &= ~AR9170_RX_ERROR_WRONG_RA; + + if (error & AR9170_RX_ERROR_DECRYPT) { + error &= ~AR9170_RX_ERROR_DECRYPT; + /* + * Rx decryption is done in place, + * the original data is lost anyway. + */ + + return -EINVAL; + } + + /* drop any other error frames */ + if (unlikely(error)) { + /* TODO: update netdevice's RX dropped/errors statistics */ + + if (ar9170_nag_limiter(ar)) + wiphy_debug(ar->hw->wiphy, + "received frame with suspicious error code (%#x).\n", + error); + + return -EINVAL; + } + + status->band = ar->channel->band; + status->freq = ar->channel->center_freq; + + switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { + case AR9170_RX_STATUS_MODULATION_CCK: + if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) + status->flag |= RX_FLAG_SHORTPRE; + switch (head->plcp[0]) { + case 0x0a: + status->rate_idx = 0; + break; + case 0x14: + status->rate_idx = 1; + break; + case 0x37: + status->rate_idx = 2; + break; + case 0x6e: + status->rate_idx = 3; + break; + default: + if (ar9170_nag_limiter(ar)) + wiphy_err(ar->hw->wiphy, + "invalid plcp cck rate (%x).\n", + head->plcp[0]); + return -EINVAL; + } + break; + + case AR9170_RX_STATUS_MODULATION_DUPOFDM: + case AR9170_RX_STATUS_MODULATION_OFDM: + switch (head->plcp[0] & 0xf) { + case 0xb: + status->rate_idx = 0; + break; + case 0xf: + status->rate_idx = 1; + break; + case 0xa: + status->rate_idx = 2; + break; + case 0xe: + status->rate_idx = 3; + break; + case 0x9: + status->rate_idx = 4; + break; + case 0xd: + status->rate_idx = 5; + break; + case 0x8: + status->rate_idx = 6; + break; + case 0xc: + status->rate_idx = 7; + break; + default: + if (ar9170_nag_limiter(ar)) + wiphy_err(ar->hw->wiphy, + "invalid plcp ofdm rate (%x).\n", + head->plcp[0]); + return -EINVAL; + } + if (status->band == IEEE80211_BAND_2GHZ) + status->rate_idx += 4; + break; + + case AR9170_RX_STATUS_MODULATION_HT: + if (head->plcp[3] & 0x80) + status->flag |= RX_FLAG_40MHZ; + if (head->plcp[6] & 0x80) + status->flag |= RX_FLAG_SHORT_GI; + + status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); + status->flag |= RX_FLAG_HT; + break; + + default: + if (ar9170_nag_limiter(ar)) + wiphy_err(ar->hw->wiphy, "invalid modulation\n"); + return -EINVAL; + } + + return 0; +} + +static void ar9170_rx_phy_status(struct ar9170 *ar, + struct ar9170_rx_phystatus *phy, + struct ieee80211_rx_status *status) +{ + int i; + + BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); + + for (i = 0; i < 3; i++) + if (phy->rssi[i] != 0x80) + status->antenna |= BIT(i); + + /* post-process RSSI */ + for (i = 0; i < 7; i++) + if (phy->rssi[i] & 0x80) + phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; + + /* TODO: we could do something with phy_errors */ + status->signal = ar->noise[0] + phy->rssi_combined; +} + +static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) +{ + struct sk_buff *skb; + int reserved = 0; + struct ieee80211_hdr *hdr = (void *) buf; + + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + reserved += NET_IP_ALIGN; + + if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) + reserved += NET_IP_ALIGN; + } + + if (ieee80211_has_a4(hdr->frame_control)) + reserved += NET_IP_ALIGN; + + reserved = 32 + (reserved & NET_IP_ALIGN); + + skb = dev_alloc_skb(len + reserved); + if (likely(skb)) { + skb_reserve(skb, reserved); + memcpy(skb_put(skb, len), buf, len); + } + + return skb; +} + +/* + * If the frame alignment is right (or the kernel has + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there + * is only a single MPDU in the USB frame, then we could + * submit to mac80211 the SKB directly. However, since + * there may be multiple packets in one SKB in stream + * mode, and we need to observe the proper ordering, + * this is non-trivial. + */ + +static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +{ + struct ar9170_rx_head *head; + struct ar9170_rx_macstatus *mac; + struct ar9170_rx_phystatus *phy = NULL; + struct ieee80211_rx_status status; + struct sk_buff *skb; + int mpdu_len; + + if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) + return ; + + /* Received MPDU */ + mpdu_len = len - sizeof(*mac); + + mac = (void *)(buf + mpdu_len); + if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { + /* this frame is too damaged and can't be used - drop it */ + + return ; + } + + switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { + case AR9170_RX_STATUS_MPDU_FIRST: + /* first mpdu packet has the plcp header */ + if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { + head = (void *) buf; + memcpy(&ar->rx_mpdu.plcp, (void *) buf, + sizeof(struct ar9170_rx_head)); + + mpdu_len -= sizeof(struct ar9170_rx_head); + buf += sizeof(struct ar9170_rx_head); + ar->rx_mpdu.has_plcp = true; + } else { + if (ar9170_nag_limiter(ar)) + wiphy_err(ar->hw->wiphy, + "plcp info is clipped.\n"); + return ; + } + break; + + case AR9170_RX_STATUS_MPDU_LAST: + /* last mpdu has a extra tail with phy status information */ + + if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { + mpdu_len -= sizeof(struct ar9170_rx_phystatus); + phy = (void *)(buf + mpdu_len); + } else { + if (ar9170_nag_limiter(ar)) + wiphy_err(ar->hw->wiphy, + "frame tail is clipped.\n"); + return ; + } + + case AR9170_RX_STATUS_MPDU_MIDDLE: + /* middle mpdus are just data */ + if (unlikely(!ar->rx_mpdu.has_plcp)) { + if (!ar9170_nag_limiter(ar)) + return ; + + wiphy_err(ar->hw->wiphy, + "rx stream did not start with a first_mpdu frame tag.\n"); + + return ; + } + + head = &ar->rx_mpdu.plcp; + break; + + case AR9170_RX_STATUS_MPDU_SINGLE: + /* single mpdu - has plcp (head) and phy status (tail) */ + head = (void *) buf; + + mpdu_len -= sizeof(struct ar9170_rx_head); + mpdu_len -= sizeof(struct ar9170_rx_phystatus); + + buf += sizeof(struct ar9170_rx_head); + phy = (void *)(buf + mpdu_len); + break; + + default: + BUG_ON(1); + break; + } + + if (unlikely(mpdu_len < FCS_LEN)) + return ; + + memset(&status, 0, sizeof(status)); + if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) + return ; + + if (phy) + ar9170_rx_phy_status(ar, phy, &status); + + skb = ar9170_rx_copy_data(buf, mpdu_len); + if (likely(skb)) { + memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); + ieee80211_rx_irqsafe(ar->hw, skb); + } +} + +void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) +{ + unsigned int i, tlen, resplen, wlen = 0, clen = 0; + u8 *tbuf, *respbuf; + + tbuf = skb->data; + tlen = skb->len; + + while (tlen >= 4) { + clen = tbuf[1] << 8 | tbuf[0]; + wlen = ALIGN(clen, 4); + + /* check if this is stream has a valid tag.*/ + if (tbuf[2] != 0 || tbuf[3] != 0x4e) { + /* + * TODO: handle the highly unlikely event that the + * corrupted stream has the TAG at the right position. + */ + + /* check if the frame can be repaired. */ + if (!ar->rx_failover_missing) { + /* this is no "short read". */ + if (ar9170_nag_limiter(ar)) { + wiphy_err(ar->hw->wiphy, + "missing tag!\n"); + goto err_telluser; + } else + goto err_silent; + } + + if (ar->rx_failover_missing > tlen) { + if (ar9170_nag_limiter(ar)) { + wiphy_err(ar->hw->wiphy, + "possible multi stream corruption!\n"); + goto err_telluser; + } else + goto err_silent; + } + + memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { + /* + * nested ar9170_rx call! + * termination is guranteed, even when the + * combined frame also have a element with + * a bad tag. + */ + + ar->rx_failover_missing = 0; + ar9170_rx(ar, ar->rx_failover); + + skb_reset_tail_pointer(ar->rx_failover); + skb_trim(ar->rx_failover, 0); + } + + return ; + } + + /* check if stream is clipped */ + if (wlen > tlen - 4) { + if (ar->rx_failover_missing) { + /* TODO: handle double stream corruption. */ + if (ar9170_nag_limiter(ar)) { + wiphy_err(ar->hw->wiphy, + "double rx stream corruption!\n"); + goto err_telluser; + } else + goto err_silent; + } + + /* + * save incomplete data set. + * the firmware will resend the missing bits when + * the rx - descriptor comes round again. + */ + + memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); + ar->rx_failover_missing = clen - tlen; + return ; + } + resplen = clen; + respbuf = tbuf + 4; + tbuf += wlen + 4; + tlen -= wlen + 4; + + i = 0; + + /* weird thing, but this is the same in the original driver */ + while (resplen > 2 && i < 12 && + respbuf[0] == 0xff && respbuf[1] == 0xff) { + i += 2; + resplen -= 2; + respbuf += 2; + } + + if (resplen < 4) + continue; + + /* found the 6 * 0xffff marker? */ + if (i == 12) + ar9170_handle_command_response(ar, respbuf, resplen); + else + ar9170_handle_mpdu(ar, respbuf, clen); + } + + if (tlen) { + if (net_ratelimit()) + wiphy_err(ar->hw->wiphy, + "%d bytes of unprocessed data left in rx stream!\n", + tlen); + + goto err_telluser; + } + + return ; + +err_telluser: + wiphy_err(ar->hw->wiphy, + "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n", + clen, wlen, tlen, ar->rx_failover_missing); + + if (ar->rx_failover_missing) + print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, + ar->rx_failover->data, + ar->rx_failover->len); + + print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, + skb->data, skb->len); + + wiphy_err(ar->hw->wiphy, + "If you see this message frequently, please check your hardware and cables.\n"); + +err_silent: + if (ar->rx_failover_missing) { + skb_reset_tail_pointer(ar->rx_failover); + skb_trim(ar->rx_failover, 0); + ar->rx_failover_missing = 0; + } +} + +#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ +do { \ + queue.aifs = ai_fs; \ + queue.cw_min = cwmin; \ + queue.cw_max = cwmax; \ + queue.txop = _txop; \ +} while (0) + +static int ar9170_op_start(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + int err, i; + + mutex_lock(&ar->mutex); + + /* reinitialize queues statistics */ + memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); + for (i = 0; i < __AR9170_NUM_TXQ; i++) + ar->tx_stats[i].limit = AR9170_TXQ_DEPTH; + + /* reset QoS defaults */ + AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ + AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ + AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ + AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ + AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ + + /* set sane AMPDU defaults */ + ar->global_ampdu_density = 6; + ar->global_ampdu_factor = 3; + + ar->bad_hw_nagger = jiffies; + + err = ar->open(ar); + if (err) + goto out; + + err = ar9170_init_mac(ar); + if (err) + goto out; + + err = ar9170_set_qos(ar); + if (err) + goto out; + + err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); + if (err) + goto out; + + err = ar9170_init_rf(ar); + if (err) + goto out; + + /* start DMA */ + err = ar9170_write_reg(ar, 0x1c3d30, 0x100); + if (err) + goto out; + + ar->state = AR9170_STARTED; + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_op_stop(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + unsigned int i; + + if (IS_STARTED(ar)) + ar->state = AR9170_IDLE; + + cancel_delayed_work_sync(&ar->tx_janitor); +#ifdef CONFIG_AR9170_LEDS + cancel_delayed_work_sync(&ar->led_work); +#endif + cancel_work_sync(&ar->beacon_work); + + mutex_lock(&ar->mutex); + + if (IS_ACCEPTING_CMD(ar)) { + ar9170_set_leds_state(ar, 0); + + /* stop DMA */ + ar9170_write_reg(ar, 0x1c3d30, 0); + ar->stop(ar); + } + + for (i = 0; i < __AR9170_NUM_TXQ; i++) { + skb_queue_purge(&ar->tx_pending[i]); + skb_queue_purge(&ar->tx_status[i]); + } + + mutex_unlock(&ar->mutex); +} + +static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + struct ar9170_tx_control *txc; + struct ieee80211_tx_info *info; + struct ieee80211_tx_rate *txrate; + struct ar9170_tx_info *arinfo; + unsigned int queue = skb_get_queue_mapping(skb); + u16 keytype = 0; + u16 len, icv = 0; + + BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); + + hdr = (void *)skb->data; + info = IEEE80211_SKB_CB(skb); + len = skb->len; + + txc = (void *)skb_push(skb, sizeof(*txc)); + + if (info->control.hw_key) { + icv = info->control.hw_key->icv_len; + + switch (info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + keytype = AR9170_TX_MAC_ENCR_RC4; + break; + case WLAN_CIPHER_SUITE_CCMP: + keytype = AR9170_TX_MAC_ENCR_AES; + break; + default: + WARN_ON(1); + goto err_out; + } + } + + /* Length */ + txc->length = cpu_to_le16(len + icv + 4); + + txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | + AR9170_TX_MAC_BACKOFF); + txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << + AR9170_TX_MAC_QOS_SHIFT); + txc->mac_control |= cpu_to_le16(keytype); + txc->phy_control = cpu_to_le32(0); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); + + txrate = &info->control.rates[0]; + if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + + arinfo = (void *)info->rate_driver_data; + arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { + /* + * WARNING: + * Putting the QoS queue bits into an unexplored territory is + * certainly not elegant. + * + * In my defense: This idea provides a reasonable way to + * smuggle valuable information to the tx_status callback. + * Also, the idea behind this bit-abuse came straight from + * the original driver code. + */ + + txc->phy_control |= + cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); + + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); + } + + return 0; + +err_out: + skb_pull(skb, sizeof(*txc)); + return -EINVAL; +} + +static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc; + struct ieee80211_tx_info *info; + struct ieee80211_rate *rate = NULL; + struct ieee80211_tx_rate *txrate; + u32 power, chains; + + txc = (void *) skb->data; + info = IEEE80211_SKB_CB(skb); + txrate = &info->control.rates[0]; + + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); + + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); + + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); + /* this works because 40 MHz is 2 and dup is 3 */ + if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); + + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); + + if (txrate->flags & IEEE80211_TX_RC_MCS) { + u32 r = txrate->idx; + u8 *txpower; + + /* heavy clip control */ + txc->phy_control |= cpu_to_le32((r & 0x7) << 7); + + r <<= AR9170_TX_PHY_MCS_SHIFT; + BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK); + + txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); + + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { + if (info->band == IEEE80211_BAND_5GHZ) + txpower = ar->power_5G_ht40; + else + txpower = ar->power_2G_ht40; + } else { + if (info->band == IEEE80211_BAND_5GHZ) + txpower = ar->power_5G_ht20; + else + txpower = ar->power_2G_ht20; + } + + power = txpower[(txrate->idx) & 7]; + } else { + u8 *txpower; + u32 mod; + u32 phyrate; + u8 idx = txrate->idx; + + if (info->band != IEEE80211_BAND_2GHZ) { + idx += 4; + txpower = ar->power_5G_leg; + mod = AR9170_TX_PHY_MOD_OFDM; + } else { + if (idx < 4) { + txpower = ar->power_2G_cck; + mod = AR9170_TX_PHY_MOD_CCK; + } else { + mod = AR9170_TX_PHY_MOD_OFDM; + txpower = ar->power_2G_ofdm; + } + } + + rate = &__ar9170_ratetable[idx]; + + phyrate = rate->hw_value & 0xF; + power = txpower[(rate->hw_value & 0x30) >> 4]; + phyrate <<= AR9170_TX_PHY_MCS_SHIFT; + + txc->phy_control |= cpu_to_le32(mod); + txc->phy_control |= cpu_to_le32(phyrate); + } + + power <<= AR9170_TX_PHY_TX_PWR_SHIFT; + power &= AR9170_TX_PHY_TX_PWR_MASK; + txc->phy_control |= cpu_to_le32(power); + + /* set TX chains */ + if (ar->eeprom.tx_mask == 1) { + chains = AR9170_TX_PHY_TXCHAIN_1; + } else { + chains = AR9170_TX_PHY_TXCHAIN_2; + + /* >= 36M legacy OFDM - use only one chain */ + if (rate && rate->bitrate >= 360) + chains = AR9170_TX_PHY_TXCHAIN_1; + } + txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); +} + +static void ar9170_tx(struct ar9170 *ar) +{ + struct sk_buff *skb; + unsigned long flags; + struct ieee80211_tx_info *info; + struct ar9170_tx_info *arinfo; + unsigned int i, frames, frames_failed, remaining_space; + int err; + bool schedule_garbagecollector = false; + + BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); + + if (unlikely(!IS_STARTED(ar))) + return ; + + remaining_space = AR9170_TX_MAX_PENDING; + + for (i = 0; i < __AR9170_NUM_TXQ; i++) { + spin_lock_irqsave(&ar->tx_stats_lock, flags); + frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, + skb_queue_len(&ar->tx_pending[i])); + + if (remaining_space < frames) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "tx quota reached queue:%d, " + "remaining slots:%d, needed:%d\n", + i, remaining_space, frames); +#endif /* AR9170_QUEUE_DEBUG */ + frames = remaining_space; + } + + ar->tx_stats[i].len += frames; + ar->tx_stats[i].count += frames; + if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, "queue %d full\n", i); + wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n"); + ar9170_dump_txqueue(ar, &ar->tx_pending[i]); + ar9170_dump_txqueue(ar, &ar->tx_status[i]); +#endif /* AR9170_QUEUE_DEBUG */ + +#ifdef AR9170_QUEUE_STOP_DEBUG + wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ + ieee80211_stop_queue(ar->hw, i); + } + + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + if (!frames) + continue; + + frames_failed = 0; + while (frames) { + skb = skb_dequeue(&ar->tx_pending[i]); + if (unlikely(!skb)) { + frames_failed += frames; + frames = 0; + break; + } + + info = IEEE80211_SKB_CB(skb); + arinfo = (void *) info->rate_driver_data; + + /* TODO: cancel stuck frames */ + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); + +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + + err = ar->tx(ar, skb); + if (unlikely(err)) { + frames_failed++; + dev_kfree_skb_any(skb); + } else { + remaining_space--; + schedule_garbagecollector = true; + } + + frames--; + } + +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "ar9170_tx report for queue %d\n", i); + + wiphy_debug(ar->hw->wiphy, + "unprocessed pending frames left:\n"); + ar9170_dump_txqueue(ar, &ar->tx_pending[i]); +#endif /* AR9170_QUEUE_DEBUG */ + + if (unlikely(frames_failed)) { +#ifdef AR9170_QUEUE_DEBUG + wiphy_debug(ar->hw->wiphy, + "frames failed %d =>\n", frames_failed); +#endif /* AR9170_QUEUE_DEBUG */ + + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[i].len -= frames_failed; + ar->tx_stats[i].count -= frames_failed; +#ifdef AR9170_QUEUE_STOP_DEBUG + wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ + ieee80211_wake_queue(ar->hw, i); + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + } + } + + if (!schedule_garbagecollector) + return; + + ieee80211_queue_delayed_work(ar->hw, + &ar->tx_janitor, + msecs_to_jiffies(AR9170_JANITOR_DELAY)); +} + +void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ar9170 *ar = hw->priv; + struct ieee80211_tx_info *info; + unsigned int queue; + + if (unlikely(!IS_STARTED(ar))) + goto err_free; + + if (unlikely(ar9170_tx_prepare(ar, skb))) + goto err_free; + + queue = skb_get_queue_mapping(skb); + info = IEEE80211_SKB_CB(skb); + ar9170_tx_prepare_phy(ar, skb); + skb_queue_tail(&ar->tx_pending[queue], skb); + + ar9170_tx(ar); + return; + +err_free: + dev_kfree_skb_any(skb); +} + +static int ar9170_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ar9170 *ar = hw->priv; + struct ath_common *common = &ar->common; + int err = 0; + + mutex_lock(&ar->mutex); + + if (ar->vif) { + err = -EBUSY; + goto unlock; + } + + ar->vif = vif; + memcpy(common->macaddr, vif->addr, ETH_ALEN); + + if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { + ar->rx_software_decryption = true; + ar->disable_offload = true; + } + + ar->cur_filter = 0; + err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); + if (err) + goto unlock; + + err = ar9170_set_operating_mode(ar); + +unlock: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ar9170 *ar = hw->priv; + + mutex_lock(&ar->mutex); + ar->vif = NULL; + ar9170_update_frame_filter(ar, 0); + ar9170_set_beacon_timers(ar); + dev_kfree_skb(ar->beacon); + ar->beacon = NULL; + ar->sniffer_enabled = false; + ar->rx_software_decryption = false; + ar9170_set_operating_mode(ar); + mutex_unlock(&ar->mutex); +} + +static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_PS) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + /* + * is it long_frame_max_tx_count or short_frame_max_tx_count? + */ + + err = ar9170_set_hwretry_limit(ar, + ar->hw->conf.long_frame_max_tx_count); + if (err) + goto out; + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + + /* adjust slot time for 5 GHz */ + err = ar9170_set_slot_time(ar); + if (err) + goto out; + + err = ar9170_set_dyn_sifs_ack(ar); + if (err) + goto out; + + err = ar9170_set_channel(ar, hw->conf.channel, + AR9170_RFI_NONE, + nl80211_to_ar9170(hw->conf.channel_type)); + if (err) + goto out; + } + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) +{ + u64 mchash; + struct netdev_hw_addr *ha; + + /* always get broadcast frames */ + mchash = 1ULL << (0xff >> 2); + + netdev_hw_addr_list_for_each(ha, mc_list) + mchash |= 1ULL << (ha->addr[5] >> 2); + + return mchash; +} + +static void ar9170_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + u64 multicast) +{ + struct ar9170 *ar = hw->priv; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return ; + + mutex_lock(&ar->mutex); + + /* mask supported flags */ + *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | + FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; + ar->filter_state = *new_flags; + /* + * We can support more by setting the sniffer bit and + * then checking the error flags, later. + */ + + if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) + multicast = ~0ULL; + + if (multicast != ar->cur_mc_hash) + ar9170_update_multicast(ar, multicast); + + if (changed_flags & FIF_CONTROL) { + u32 filter = AR9170_MAC_REG_FTF_PSPOLL | + AR9170_MAC_REG_FTF_RTS | + AR9170_MAC_REG_FTF_CTS | + AR9170_MAC_REG_FTF_ACK | + AR9170_MAC_REG_FTF_CFE | + AR9170_MAC_REG_FTF_CFE_ACK; + + if (*new_flags & FIF_CONTROL) + filter |= ar->cur_filter; + else + filter &= (~ar->cur_filter); + + ar9170_update_frame_filter(ar, filter); + } + + if (changed_flags & FIF_PROMISC_IN_BSS) { + ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; + ar9170_set_operating_mode(ar); + } + + mutex_unlock(&ar->mutex); +} + + +static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct ar9170 *ar = hw->priv; + struct ath_common *common = &ar->common; + int err = 0; + + mutex_lock(&ar->mutex); + + if (changed & BSS_CHANGED_BSSID) { + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + err = ar9170_set_operating_mode(ar); + if (err) + goto out; + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) + ar->enable_beacon = bss_conf->enable_beacon; + + if (changed & BSS_CHANGED_BEACON) { + err = ar9170_update_beacon(ar); + if (err) + goto out; + } + + if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_INT)) { + err = ar9170_set_beacon_timers(ar); + if (err) + goto out; + } + + if (changed & BSS_CHANGED_ASSOC) { +#ifndef CONFIG_AR9170_LEDS + /* enable assoc LED. */ + err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); +#endif /* CONFIG_AR9170_LEDS */ + } + + if (changed & BSS_CHANGED_HT) { + /* TODO */ + err = 0; + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + err = ar9170_set_slot_time(ar); + if (err) + goto out; + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + err = ar9170_set_basic_rates(ar); + if (err) + goto out; + } + +out: + mutex_unlock(&ar->mutex); +} + +static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + int err; + u64 tsf; +#define NR 3 + static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, + AR9170_MAC_REG_TSF_L, + AR9170_MAC_REG_TSF_H }; + u32 val[NR]; + int loops = 0; + + mutex_lock(&ar->mutex); + + while (loops++ < 10) { + err = ar9170_read_mreg(ar, NR, addr, val); + if (err || val[0] == val[2]) + break; + } + + mutex_unlock(&ar->mutex); + + if (WARN_ON(err)) + return 0; + tsf = val[0]; + tsf = (tsf << 32) | val[1]; + return tsf; +#undef NR +} + +static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ar9170 *ar = hw->priv; + int err = 0, i; + u8 ktype; + + if ((!ar->vif) || (ar->disable_offload)) + return -EOPNOTSUPP; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + ktype = AR9170_ENC_ALG_WEP64; + break; + case WLAN_CIPHER_SUITE_WEP104: + ktype = AR9170_ENC_ALG_WEP128; + break; + case WLAN_CIPHER_SUITE_TKIP: + ktype = AR9170_ENC_ALG_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + ktype = AR9170_ENC_ALG_AESCCMP; + break; + default: + return -EOPNOTSUPP; + } + + mutex_lock(&ar->mutex); + if (cmd == SET_KEY) { + if (unlikely(!IS_STARTED(ar))) { + err = -EOPNOTSUPP; + goto out; + } + + /* group keys need all-zeroes address */ + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + sta = NULL; + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + for (i = 0; i < 64; i++) + if (!(ar->usedkeys & BIT(i))) + break; + if (i == 64) { + ar->rx_software_decryption = true; + ar9170_set_operating_mode(ar); + err = -ENOSPC; + goto out; + } + } else { + i = 64 + key->keyidx; + } + + key->hw_key_idx = i; + + err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, + key->key, min_t(u8, 16, key->keylen)); + if (err) + goto out; + + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { + err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, + ktype, 1, key->key + 16, 16); + if (err) + goto out; + + /* + * hardware is not capable generating the MMIC + * for fragmented frames! + */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + } + + if (i < 64) + ar->usedkeys |= BIT(i); + + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + } else { + if (unlikely(!IS_STARTED(ar))) { + /* The device is gone... together with the key ;-) */ + err = 0; + goto out; + } + + err = ar9170_disable_key(ar, key->hw_key_idx); + if (err) + goto out; + + if (key->hw_key_idx < 64) { + ar->usedkeys &= ~BIT(key->hw_key_idx); + } else { + err = ar9170_upload_key(ar, key->hw_key_idx, NULL, + AR9170_ENC_ALG_NONE, 0, + NULL, 0); + if (err) + goto out; + + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { + err = ar9170_upload_key(ar, key->hw_key_idx, + NULL, + AR9170_ENC_ALG_NONE, 1, + NULL, 0); + if (err) + goto out; + } + + } + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); + ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + +out: + mutex_unlock(&ar->mutex); + + return err; +} + +static int ar9170_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ar9170 *ar = hw->priv; + u32 val; + int err; + + mutex_lock(&ar->mutex); + err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); + ar->stats.dot11ACKFailureCount += val; + + memcpy(stats, &ar->stats, sizeof(*stats)); + mutex_unlock(&ar->mutex); + + return 0; +} + +static int ar9170_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct ar9170 *ar = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + + if (idx != 0) + return -ENOENT; + + /* TODO: update noise value, e.g. call ar9170_set_channel */ + + survey->channel = conf->channel; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = ar->noise[0]; + + return 0; +} + +static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct ar9170 *ar = hw->priv; + int ret; + + mutex_lock(&ar->mutex); + if (queue < __AR9170_NUM_TXQ) { + memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], + param, sizeof(*param)); + + ret = ar9170_set_qos(ar); + } else { + ret = -EINVAL; + } + + mutex_unlock(&ar->mutex); + return ret; +} + +static int ar9170_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size) +{ + switch (action) { + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + /* Handled by firmware */ + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static const struct ieee80211_ops ar9170_ops = { + .start = ar9170_op_start, + .stop = ar9170_op_stop, + .tx = ar9170_op_tx, + .add_interface = ar9170_op_add_interface, + .remove_interface = ar9170_op_remove_interface, + .config = ar9170_op_config, + .prepare_multicast = ar9170_op_prepare_multicast, + .configure_filter = ar9170_op_configure_filter, + .conf_tx = ar9170_conf_tx, + .bss_info_changed = ar9170_op_bss_info_changed, + .get_tsf = ar9170_op_get_tsf, + .set_key = ar9170_set_key, + .get_stats = ar9170_get_stats, + .get_survey = ar9170_get_survey, + .ampdu_action = ar9170_ampdu_action, +}; + +void *ar9170_alloc(size_t priv_size) +{ + struct ieee80211_hw *hw; + struct ar9170 *ar; + struct sk_buff *skb; + int i; + + /* + * this buffer is used for rx stream reconstruction. + * Under heavy load this device (or the transport layer?) + * tends to split the streams into separate rx descriptors. + */ + + skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); + if (!skb) + goto err_nomem; + + hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); + if (!hw) + goto err_nomem; + + ar = hw->priv; + ar->hw = hw; + ar->rx_failover = skb; + + mutex_init(&ar->mutex); + spin_lock_init(&ar->cmdlock); + spin_lock_init(&ar->tx_stats_lock); + for (i = 0; i < __AR9170_NUM_TXQ; i++) { + skb_queue_head_init(&ar->tx_status[i]); + skb_queue_head_init(&ar->tx_pending[i]); + } + ar9170_rx_reset_rx_mpdu(ar); + INIT_WORK(&ar->beacon_work, ar9170_new_beacon); + INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); + + /* all hw supports 2.4 GHz, so set channel to 1 by default */ + ar->channel = &ar9170_2ghz_chantable[0]; + + /* first part of wiphy init */ + ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); + ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM; + + ar->hw->queues = __AR9170_NUM_TXQ; + ar->hw->extra_tx_headroom = 8; + + ar->hw->max_rates = 1; + ar->hw->max_rate_tries = 3; + + for (i = 0; i < ARRAY_SIZE(ar->noise); i++) + ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ + + return ar; + +err_nomem: + kfree_skb(skb); + return ERR_PTR(-ENOMEM); +} + +static int ar9170_read_eeprom(struct ar9170 *ar) +{ +#define RW 8 /* number of words to read at once */ +#define RB (sizeof(u32) * RW) + struct ath_regulatory *regulatory = &ar->common.regulatory; + u8 *eeprom = (void *)&ar->eeprom; + u8 *addr = ar->eeprom.mac_address; + __le32 offsets[RW]; + unsigned int rx_streams, tx_streams, tx_params = 0; + int i, j, err, bands = 0; + + BUILD_BUG_ON(sizeof(ar->eeprom) & 3); + + BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); +#ifndef __CHECKER__ + /* don't want to handle trailing remains */ + BUILD_BUG_ON(sizeof(ar->eeprom) % RB); +#endif + + for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { + for (j = 0; j < RW; j++) + offsets[j] = cpu_to_le32(AR9170_EEPROM_START + + RB * i + 4 * j); + + err = ar->exec_cmd(ar, AR9170_CMD_RREG, + RB, (u8 *) &offsets, + RB, eeprom + RB * i); + if (err) + return err; + } + +#undef RW +#undef RB + + if (ar->eeprom.length == cpu_to_le16(0xFFFF)) + return -ENODATA; + + if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; + bands++; + } + if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { + ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; + bands++; + } + + rx_streams = hweight8(ar->eeprom.rx_mask); + tx_streams = hweight8(ar->eeprom.tx_mask); + + if (rx_streams != tx_streams) + tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; + + if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) + tx_params = (tx_streams - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + + ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; + ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; + + /* + * I measured this, a bandswitch takes roughly + * 135 ms and a frequency switch about 80. + * + * FIXME: measure these values again once EEPROM settings + * are used, that will influence them! + */ + if (bands == 2) + ar->hw->channel_change_time = 135 * 1000; + else + ar->hw->channel_change_time = 80 * 1000; + + regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); + regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); + + /* second part of wiphy init */ + SET_IEEE80211_PERM_ADDR(ar->hw, addr); + + return bands ? 0 : -EINVAL; +} + +static int ar9170_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ar9170 *ar = hw->priv; + + return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); +} + +int ar9170_register(struct ar9170 *ar, struct device *pdev) +{ + struct ath_regulatory *regulatory = &ar->common.regulatory; + int err; + + /* try to read EEPROM, init MAC addr */ + err = ar9170_read_eeprom(ar); + if (err) + goto err_out; + + err = ath_regd_init(regulatory, ar->hw->wiphy, + ar9170_reg_notifier); + if (err) + goto err_out; + + err = ieee80211_register_hw(ar->hw); + if (err) + goto err_out; + + if (!ath_is_world_regd(regulatory)) + regulatory_hint(ar->hw->wiphy, regulatory->alpha2); + + err = ar9170_init_leds(ar); + if (err) + goto err_unreg; + +#ifdef CONFIG_AR9170_LEDS + err = ar9170_register_leds(ar); + if (err) + goto err_unreg; +#endif /* CONFIG_AR9170_LEDS */ + + dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", + wiphy_name(ar->hw->wiphy)); + + ar->registered = true; + return 0; + +err_unreg: + ieee80211_unregister_hw(ar->hw); + +err_out: + return err; +} + +void ar9170_unregister(struct ar9170 *ar) +{ + if (ar->registered) { +#ifdef CONFIG_AR9170_LEDS + ar9170_unregister_leds(ar); +#endif /* CONFIG_AR9170_LEDS */ + + ieee80211_unregister_hw(ar->hw); + } + + kfree_skb(ar->rx_failover); + mutex_destroy(&ar->mutex); +} diff --git a/trunk/drivers/net/wireless/ath/ar9170/phy.c b/trunk/drivers/net/wireless/ath/ar9170/phy.c new file mode 100644 index 000000000000..0dbfcf79ac96 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/phy.c @@ -0,0 +1,1719 @@ +/* + * Atheros AR9170 driver + * + * PHY and RF code + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "ar9170.h" +#include "cmd.h" + +static int ar9170_init_power_cal(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); + ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +struct ar9170_phy_init { + u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; +}; + +static struct ar9170_phy_init ar5416_phy_init[] = { + { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, + { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, + { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, + { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, + { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, + { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, + { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, + { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, + { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, + { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, + { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, + { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, + { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, + { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, + { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, + { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, + { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, + { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, + { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, + { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, + { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, + { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, + { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, + { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, + { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, + { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, + { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, + { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, + { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, + { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, + { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, + { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, + { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, + { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, + { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, + { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, + { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, + { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, + { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, + { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, + { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, + { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, + { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, + { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, + { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, + { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, + { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, + { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, + { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, + { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, + { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, + { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, + { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, + { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, + { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, + { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, + { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, + { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, + { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, + { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, + { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, + { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, + { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, + { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, + { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, + { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, + { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, + { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, + { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, + { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, + { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, + { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, + { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, + { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, + { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, + { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, + { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, + { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, + { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, + { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, + { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, + { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, + { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, + { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, + { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, + { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, + { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, + { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, + { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, + { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, + { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, + { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, + { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, + { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, + { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, + { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, + { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, + { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, + { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, + { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, + { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, + { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, + { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, + { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, + { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, + { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, + { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, + { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, + { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, + { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, + { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, + { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, + { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, + { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, + { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, + { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, + { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, + { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, + { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, + { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, + { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, + { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, + { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, + { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, + { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, + { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, + { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, + { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, + { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, + { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, + { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, + { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, + { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, + { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, + { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, + { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, + { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, + { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, + { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, + { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, + { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, + { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, + { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, + { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, + { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, + { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, + { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, + { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, + { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, + { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, + { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, + { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, + { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, + { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, + { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, + { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, + { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, + { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, + { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, + { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, + { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, + { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, + { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, + { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, + { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, + { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, + { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, + { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, + { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, + { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, + { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, + { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, + { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, + { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, + { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, +/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ + { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, + { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, + { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, + { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, + { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, + { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, + { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, + { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, + { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, + { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, + { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, + { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, + { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, + { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, + { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, + { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } +}; + +/* + * look up a certain register in ar5416_phy_init[] and return the init. value + * for the band and bandwidth given. Return 0 if register address not found. + */ +static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { + if (ar5416_phy_init[i].reg != reg) + continue; + + if (is_2ghz) { + if (is_40mhz) + return ar5416_phy_init[i]._2ghz_40; + else + return ar5416_phy_init[i]._2ghz_20; + } else { + if (is_40mhz) + return ar5416_phy_init[i]._5ghz_40; + else + return ar5416_phy_init[i]._5ghz_20; + } + } + return 0; +} + +/* + * initialize some phy regs from eeprom values in modal_header[] + * acc. to band and bandwith + */ +static int ar9170_init_phy_from_eeprom(struct ar9170 *ar, + bool is_2ghz, bool is_40mhz) +{ + static const u8 xpd2pd[16] = { + 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, + 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2 + }; + u32 defval, newval; + /* pointer to the modal_header acc. to band */ + struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; + + ar9170_regwrite_begin(ar); + + /* ant common control (index 0) */ + newval = le32_to_cpu(m->antCtrlCommon); + ar9170_regwrite(0x1c5964, newval); + + /* ant control chain 0 (index 1) */ + newval = le32_to_cpu(m->antCtrlChain[0]); + ar9170_regwrite(0x1c5960, newval); + + /* ant control chain 2 (index 2) */ + newval = le32_to_cpu(m->antCtrlChain[1]); + ar9170_regwrite(0x1c7960, newval); + + /* SwSettle (index 3) */ + if (!is_40mhz) { + defval = ar9170_get_default_phy_reg_val(0x1c5844, + is_2ghz, is_40mhz); + newval = (defval & ~0x3f80) | + ((m->switchSettling & 0x7f) << 7); + ar9170_regwrite(0x1c5844, newval); + } + + /* adcDesired, pdaDesired (index 4) */ + defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz); + newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) | + ((u8)m->adcDesiredSize); + ar9170_regwrite(0x1c5850, newval); + + /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ + defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz); + newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) | + (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn; + ar9170_regwrite(0x1c5834, newval); + + /* TxEndToRxOn (index 6) */ + defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz); + newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16); + ar9170_regwrite(0x1c5828, newval); + + /* thresh62 (index 7) */ + defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz); + newval = (defval & ~0x7f000) | (m->thresh62 << 12); + ar9170_regwrite(0x1c8864, newval); + + /* tx/rx attenuation chain 0 (index 8) */ + defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz); + newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12); + ar9170_regwrite(0x1c5848, newval); + + /* tx/rx attenuation chain 2 (index 9) */ + defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz); + newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12); + ar9170_regwrite(0x1c7848, newval); + + /* tx/rx margin chain 0 (index 10) */ + defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz); + newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18); + /* bsw margin chain 0 for 5GHz only */ + if (!is_2ghz) + newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10); + ar9170_regwrite(0x1c620c, newval); + + /* tx/rx margin chain 2 (index 11) */ + defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz); + newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18); + ar9170_regwrite(0x1c820c, newval); + + /* iqCall, iqCallq chain 0 (index 12) */ + defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz); + newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) | + ((u8)m->iqCalQCh[0] & 0x1f); + ar9170_regwrite(0x1c5920, newval); + + /* iqCall, iqCallq chain 2 (index 13) */ + defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz); + newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) | + ((u8)m->iqCalQCh[1] & 0x1f); + ar9170_regwrite(0x1c7920, newval); + + /* xpd gain mask (index 14) */ + defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz); + newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16); + ar9170_regwrite(0x1c6258, newval); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) +{ + int i, err; + u32 val; + bool is_2ghz = band == IEEE80211_BAND_2GHZ; + bool is_40mhz = conf_is_ht40(&ar->hw->conf); + + ar9170_regwrite_begin(ar); + + for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { + if (is_40mhz) { + if (is_2ghz) + val = ar5416_phy_init[i]._2ghz_40; + else + val = ar5416_phy_init[i]._5ghz_40; + } else { + if (is_2ghz) + val = ar5416_phy_init[i]._2ghz_20; + else + val = ar5416_phy_init[i]._5ghz_20; + } + + ar9170_regwrite(ar5416_phy_init[i].reg, val); + } + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); + if (err) + return err; + + err = ar9170_init_power_cal(ar); + if (err) + return err; + + /* XXX: remove magic! */ + if (is_2ghz) + err = ar9170_write_reg(ar, 0x1d4014, 0x5163); + else + err = ar9170_write_reg(ar, 0x1d4014, 0x5143); + + return err; +} + +struct ar9170_rf_init { + u32 reg, _5ghz, _2ghz; +}; + +static struct ar9170_rf_init ar9170_rf_init[] = { + /* bank 0 */ + { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, + { 0x1c58e0, 0x02008020, 0x02008020}, + /* bank 1 */ + { 0x1c58b0, 0x02108421, 0x02108421}, + { 0x1c58ec, 0x00000008, 0x00000008}, + /* bank 2 */ + { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, + { 0x1c58e0, 0x00000420, 0x00000420}, + /* bank 3 */ + { 0x1c58f0, 0x01400018, 0x01c00018}, + /* bank 4 */ + { 0x1c58b0, 0x000001a1, 0x000001a1}, + { 0x1c58e8, 0x00000001, 0x00000001}, + /* bank 5 */ + { 0x1c58b0, 0x00000013, 0x00000013}, + { 0x1c58e4, 0x00000002, 0x00000002}, + /* bank 6 */ + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00002c00, 0x00002c00}, + { 0x1c58b0, 0x00004800, 0x00004800}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00006000, 0x00006000}, + { 0x1c58b0, 0x00001000, 0x00001000}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00087c00, 0x00087c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00005400, 0x00005400}, + { 0x1c58b0, 0x00000c00, 0x00000c00}, + { 0x1c58b0, 0x00001800, 0x00001800}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00002c00, 0x00002c00}, + { 0x1c58b0, 0x00003c00, 0x00003c00}, + { 0x1c58b0, 0x00003800, 0x00003800}, + { 0x1c58b0, 0x00001c00, 0x00001c00}, + { 0x1c58b0, 0x00000800, 0x00000800}, + { 0x1c58b0, 0x00000408, 0x00000408}, + { 0x1c58b0, 0x00004c15, 0x00004c15}, + { 0x1c58b0, 0x00004188, 0x00004188}, + { 0x1c58b0, 0x0000201e, 0x0000201e}, + { 0x1c58b0, 0x00010408, 0x00010408}, + { 0x1c58b0, 0x00000801, 0x00000801}, + { 0x1c58b0, 0x00000c08, 0x00000c08}, + { 0x1c58b0, 0x0000181e, 0x0000181e}, + { 0x1c58b0, 0x00001016, 0x00001016}, + { 0x1c58b0, 0x00002800, 0x00002800}, + { 0x1c58b0, 0x00004010, 0x00004010}, + { 0x1c58b0, 0x0000081c, 0x0000081c}, + { 0x1c58b0, 0x00000115, 0x00000115}, + { 0x1c58b0, 0x00000015, 0x00000015}, + { 0x1c58b0, 0x00000066, 0x00000066}, + { 0x1c58b0, 0x0000001c, 0x0000001c}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000004, 0x00000004}, + { 0x1c58b0, 0x00000015, 0x00000015}, + { 0x1c58b0, 0x0000001f, 0x0000001f}, + { 0x1c58e0, 0x00000000, 0x00000400}, + /* bank 7 */ + { 0x1c58b0, 0x000000a0, 0x000000a0}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000040, 0x00000040}, + { 0x1c58f0, 0x0000001c, 0x0000001c}, +}; + +static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) +{ + int err, i; + + ar9170_regwrite_begin(ar); + + for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) + ar9170_regwrite(ar9170_rf_init[i].reg, + band5ghz ? ar9170_rf_init[i]._5ghz + : ar9170_rf_init[i]._2ghz); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + wiphy_err(ar->hw->wiphy, "rf init failed\n"); + return err; +} + +static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, + u32 freq, enum ar9170_bw bw) +{ + int err; + u32 d0, d1, td0, td1, fd0, fd1; + u8 chansel; + u8 refsel0 = 1, refsel1 = 0; + u8 lf_synth = 0; + + switch (bw) { + case AR9170_BW_40_ABOVE: + freq += 10; + break; + case AR9170_BW_40_BELOW: + freq -= 10; + break; + case AR9170_BW_20: + break; + case __AR9170_NUM_BW: + BUG(); + } + + if (band5ghz) { + if (freq % 10) { + chansel = (freq - 4800) / 5; + } else { + chansel = ((freq - 4800) / 10) * 2; + refsel0 = 0; + refsel1 = 1; + } + chansel = byte_rev_table[chansel]; + } else { + if (freq == 2484) { + chansel = 10 + (freq - 2274) / 5; + lf_synth = 1; + } else + chansel = 16 + (freq - 2272) / 5; + chansel *= 4; + chansel = byte_rev_table[chansel]; + } + + d1 = chansel; + d0 = 0x21 | + refsel0 << 3 | + refsel1 << 2 | + lf_synth << 1; + td0 = d0 & 0x1f; + td1 = d1 & 0x1f; + fd0 = td1 << 5 | td0; + + td0 = (d0 >> 5) & 0x7; + td1 = (d1 >> 5) & 0x7; + fd1 = td1 << 5 | td0; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(0x1c58b0, fd0); + ar9170_regwrite(0x1c58e8, fd1); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + msleep(10); + + return 0; +} + +struct ar9170_phy_freq_params { + u8 coeff_exp; + u16 coeff_man; + u8 coeff_exp_shgi; + u16 coeff_man_shgi; +}; + +struct ar9170_phy_freq_entry { + u16 freq; + struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; +}; + +/* NB: must be in sync with channel tables in main! */ +static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { +/* + * freq, + * 20MHz, + * 40MHz (below), + * 40Mhz (above), + */ + { 2412, { + { 3, 21737, 3, 19563, }, + { 3, 21827, 3, 19644, }, + { 3, 21647, 3, 19482, }, + } }, + { 2417, { + { 3, 21692, 3, 19523, }, + { 3, 21782, 3, 19604, }, + { 3, 21602, 3, 19442, }, + } }, + { 2422, { + { 3, 21647, 3, 19482, }, + { 3, 21737, 3, 19563, }, + { 3, 21558, 3, 19402, }, + } }, + { 2427, { + { 3, 21602, 3, 19442, }, + { 3, 21692, 3, 19523, }, + { 3, 21514, 3, 19362, }, + } }, + { 2432, { + { 3, 21558, 3, 19402, }, + { 3, 21647, 3, 19482, }, + { 3, 21470, 3, 19323, }, + } }, + { 2437, { + { 3, 21514, 3, 19362, }, + { 3, 21602, 3, 19442, }, + { 3, 21426, 3, 19283, }, + } }, + { 2442, { + { 3, 21470, 3, 19323, }, + { 3, 21558, 3, 19402, }, + { 3, 21382, 3, 19244, }, + } }, + { 2447, { + { 3, 21426, 3, 19283, }, + { 3, 21514, 3, 19362, }, + { 3, 21339, 3, 19205, }, + } }, + { 2452, { + { 3, 21382, 3, 19244, }, + { 3, 21470, 3, 19323, }, + { 3, 21295, 3, 19166, }, + } }, + { 2457, { + { 3, 21339, 3, 19205, }, + { 3, 21426, 3, 19283, }, + { 3, 21252, 3, 19127, }, + } }, + { 2462, { + { 3, 21295, 3, 19166, }, + { 3, 21382, 3, 19244, }, + { 3, 21209, 3, 19088, }, + } }, + { 2467, { + { 3, 21252, 3, 19127, }, + { 3, 21339, 3, 19205, }, + { 3, 21166, 3, 19050, }, + } }, + { 2472, { + { 3, 21209, 3, 19088, }, + { 3, 21295, 3, 19166, }, + { 3, 21124, 3, 19011, }, + } }, + { 2484, { + { 3, 21107, 3, 18996, }, + { 3, 21192, 3, 19073, }, + { 3, 21022, 3, 18920, }, + } }, + { 4920, { + { 4, 21313, 4, 19181, }, + { 4, 21356, 4, 19220, }, + { 4, 21269, 4, 19142, }, + } }, + { 4940, { + { 4, 21226, 4, 19104, }, + { 4, 21269, 4, 19142, }, + { 4, 21183, 4, 19065, }, + } }, + { 4960, { + { 4, 21141, 4, 19027, }, + { 4, 21183, 4, 19065, }, + { 4, 21098, 4, 18988, }, + } }, + { 4980, { + { 4, 21056, 4, 18950, }, + { 4, 21098, 4, 18988, }, + { 4, 21014, 4, 18912, }, + } }, + { 5040, { + { 4, 20805, 4, 18725, }, + { 4, 20846, 4, 18762, }, + { 4, 20764, 4, 18687, }, + } }, + { 5060, { + { 4, 20723, 4, 18651, }, + { 4, 20764, 4, 18687, }, + { 4, 20682, 4, 18614, }, + } }, + { 5080, { + { 4, 20641, 4, 18577, }, + { 4, 20682, 4, 18614, }, + { 4, 20601, 4, 18541, }, + } }, + { 5180, { + { 4, 20243, 4, 18219, }, + { 4, 20282, 4, 18254, }, + { 4, 20204, 4, 18183, }, + } }, + { 5200, { + { 4, 20165, 4, 18148, }, + { 4, 20204, 4, 18183, }, + { 4, 20126, 4, 18114, }, + } }, + { 5220, { + { 4, 20088, 4, 18079, }, + { 4, 20126, 4, 18114, }, + { 4, 20049, 4, 18044, }, + } }, + { 5240, { + { 4, 20011, 4, 18010, }, + { 4, 20049, 4, 18044, }, + { 4, 19973, 4, 17976, }, + } }, + { 5260, { + { 4, 19935, 4, 17941, }, + { 4, 19973, 4, 17976, }, + { 4, 19897, 4, 17907, }, + } }, + { 5280, { + { 4, 19859, 4, 17873, }, + { 4, 19897, 4, 17907, }, + { 4, 19822, 4, 17840, }, + } }, + { 5300, { + { 4, 19784, 4, 17806, }, + { 4, 19822, 4, 17840, }, + { 4, 19747, 4, 17772, }, + } }, + { 5320, { + { 4, 19710, 4, 17739, }, + { 4, 19747, 4, 17772, }, + { 4, 19673, 4, 17706, }, + } }, + { 5500, { + { 4, 19065, 4, 17159, }, + { 4, 19100, 4, 17190, }, + { 4, 19030, 4, 17127, }, + } }, + { 5520, { + { 4, 18996, 4, 17096, }, + { 4, 19030, 4, 17127, }, + { 4, 18962, 4, 17065, }, + } }, + { 5540, { + { 4, 18927, 4, 17035, }, + { 4, 18962, 4, 17065, }, + { 4, 18893, 4, 17004, }, + } }, + { 5560, { + { 4, 18859, 4, 16973, }, + { 4, 18893, 4, 17004, }, + { 4, 18825, 4, 16943, }, + } }, + { 5580, { + { 4, 18792, 4, 16913, }, + { 4, 18825, 4, 16943, }, + { 4, 18758, 4, 16882, }, + } }, + { 5600, { + { 4, 18725, 4, 16852, }, + { 4, 18758, 4, 16882, }, + { 4, 18691, 4, 16822, }, + } }, + { 5620, { + { 4, 18658, 4, 16792, }, + { 4, 18691, 4, 16822, }, + { 4, 18625, 4, 16762, }, + } }, + { 5640, { + { 4, 18592, 4, 16733, }, + { 4, 18625, 4, 16762, }, + { 4, 18559, 4, 16703, }, + } }, + { 5660, { + { 4, 18526, 4, 16673, }, + { 4, 18559, 4, 16703, }, + { 4, 18493, 4, 16644, }, + } }, + { 5680, { + { 4, 18461, 4, 16615, }, + { 4, 18493, 4, 16644, }, + { 4, 18428, 4, 16586, }, + } }, + { 5700, { + { 4, 18396, 4, 16556, }, + { 4, 18428, 4, 16586, }, + { 4, 18364, 4, 16527, }, + } }, + { 5745, { + { 4, 18252, 4, 16427, }, + { 4, 18284, 4, 16455, }, + { 4, 18220, 4, 16398, }, + } }, + { 5765, { + { 4, 18189, 5, 32740, }, + { 4, 18220, 4, 16398, }, + { 4, 18157, 5, 32683, }, + } }, + { 5785, { + { 4, 18126, 5, 32626, }, + { 4, 18157, 5, 32683, }, + { 4, 18094, 5, 32570, }, + } }, + { 5805, { + { 4, 18063, 5, 32514, }, + { 4, 18094, 5, 32570, }, + { 4, 18032, 5, 32458, }, + } }, + { 5825, { + { 4, 18001, 5, 32402, }, + { 4, 18032, 5, 32458, }, + { 4, 17970, 5, 32347, }, + } }, + { 5170, { + { 4, 20282, 4, 18254, }, + { 4, 20321, 4, 18289, }, + { 4, 20243, 4, 18219, }, + } }, + { 5190, { + { 4, 20204, 4, 18183, }, + { 4, 20243, 4, 18219, }, + { 4, 20165, 4, 18148, }, + } }, + { 5210, { + { 4, 20126, 4, 18114, }, + { 4, 20165, 4, 18148, }, + { 4, 20088, 4, 18079, }, + } }, + { 5230, { + { 4, 20049, 4, 18044, }, + { 4, 20088, 4, 18079, }, + { 4, 20011, 4, 18010, }, + } }, +}; + +static const struct ar9170_phy_freq_params * +ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, + enum ar9170_bw bw) +{ + unsigned int chanidx = 0; + u16 freq = 2412; + + if (channel) { + chanidx = channel->hw_value; + freq = channel->center_freq; + } + + BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); + + BUILD_BUG_ON(__AR9170_NUM_BW != 3); + + WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); + + return &ar9170_phy_freq_params[chanidx].params[bw]; +} + + +int ar9170_init_rf(struct ar9170 *ar) +{ + const struct ar9170_phy_freq_params *freqpar; + __le32 cmd[7]; + int err; + + err = ar9170_init_rf_banks_0_7(ar, false); + if (err) + return err; + + err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); + if (err) + return err; + + freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); + + cmd[0] = cpu_to_le32(2412 * 1000); + cmd[1] = cpu_to_le32(0); + cmd[2] = cpu_to_le32(1); + cmd[3] = cpu_to_le32(freqpar->coeff_exp); + cmd[4] = cpu_to_le32(freqpar->coeff_man); + cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); + cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); + + /* RF_INIT echoes the command back to us */ + err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, + sizeof(cmd), (u8 *)cmd, + sizeof(cmd), (u8 *)cmd); + if (err) + return err; + + msleep(1000); + + return ar9170_echo_test(ar, 0xaabbccdd); +} + +static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) +{ + int idx = nfreqs - 2; + + while (idx >= 0) { + if (f >= freqs[idx]) + return idx; + idx--; + } + + return 0; +} + +static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) +{ + /* nothing to interpolate, it's horizontal */ + if (y2 == y1) + return y1; + + /* check if we hit one of the edges */ + if (x == x1) + return y1; + if (x == x2) + return y2; + + /* x1 == x2 is bad, hopefully == x */ + if (x2 == x1) + return y1; + + return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); +} + +static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) +{ +#define SHIFT 8 + s32 y; + + y = ar9170_interpolate_s32(x << SHIFT, + x1 << SHIFT, y1 << SHIFT, + x2 << SHIFT, y2 << SHIFT); + + /* + * XXX: unwrap this expression + * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); +#undef SHIFT +} + +static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) +{ + int i; + + for (i = 0; i < 3; i++) + if (x <= x_array[i + 1]) + break; + + return ar9170_interpolate_u8(x, + x_array[i], + y_array[i], + x_array[i + 1], + y_array[i + 1]); +} + +static int ar9170_set_freq_cal_data(struct ar9170 *ar, + struct ieee80211_channel *channel) +{ + u8 *cal_freq_pier; + u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; + u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; + int chain, idx, i; + u32 phy_data = 0; + u8 f, tmp; + + switch (channel->band) { + case IEEE80211_BAND_2GHZ: + f = channel->center_freq - 2300; + cal_freq_pier = ar->eeprom.cal_freq_pier_2G; + i = AR5416_NUM_2G_CAL_PIERS - 1; + break; + + case IEEE80211_BAND_5GHZ: + f = (channel->center_freq - 4800) / 5; + cal_freq_pier = ar->eeprom.cal_freq_pier_5G; + i = AR5416_NUM_5G_CAL_PIERS - 1; + break; + + default: + return -EINVAL; + break; + } + + for (; i >= 0; i--) { + if (cal_freq_pier[i] != 0xff) + break; + } + if (i < 0) + return -EINVAL; + + idx = ar9170_find_freq_idx(i, cal_freq_pier, f); + + ar9170_regwrite_begin(ar); + + for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { + for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { + struct ar9170_calibration_data_per_freq *cal_pier_data; + int j; + + switch (channel->band) { + case IEEE80211_BAND_2GHZ: + cal_pier_data = &ar->eeprom. + cal_pier_data_2G[chain][idx]; + break; + + case IEEE80211_BAND_5GHZ: + cal_pier_data = &ar->eeprom. + cal_pier_data_5G[chain][idx]; + break; + + default: + return -EINVAL; + } + + for (j = 0; j < 2; j++) { + vpds[j][i] = ar9170_interpolate_u8(f, + cal_freq_pier[idx], + cal_pier_data->vpd_pdg[j][i], + cal_freq_pier[idx + 1], + cal_pier_data[1].vpd_pdg[j][i]); + + pwrs[j][i] = ar9170_interpolate_u8(f, + cal_freq_pier[idx], + cal_pier_data->pwr_pdg[j][i], + cal_freq_pier[idx + 1], + cal_pier_data[1].pwr_pdg[j][i]) / 2; + } + } + + for (i = 0; i < 76; i++) { + if (i < 25) { + tmp = ar9170_interpolate_val(i, &pwrs[0][0], + &vpds[0][0]); + } else { + tmp = ar9170_interpolate_val(i - 12, + &pwrs[1][0], + &vpds[1][0]); + } + + phy_data |= tmp << ((i & 3) << 3); + if ((i & 3) == 3) { + ar9170_regwrite(0x1c6280 + chain * 0x1000 + + (i & ~3), phy_data); + phy_data = 0; + } + } + + for (i = 19; i < 32; i++) + ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), + 0x0); + } + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +static u8 ar9170_get_max_edge_power(struct ar9170 *ar, + struct ar9170_calctl_edges edges[], + u32 freq) +{ + int i; + u8 rc = AR5416_MAX_RATE_POWER; + u8 f; + if (freq < 3000) + f = freq - 2300; + else + f = (freq - 4800) / 5; + + for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { + if (edges[i].channel == 0xff) + break; + if (f == edges[i].channel) { + /* exact freq match */ + rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; + break; + } + if (i > 0 && f < edges[i].channel) { + if (f > edges[i - 1].channel && + edges[i - 1].power_flags & + AR9170_CALCTL_EDGE_FLAGS) { + /* lower channel has the inband flag set */ + rc = edges[i - 1].power_flags & + ~AR9170_CALCTL_EDGE_FLAGS; + } + break; + } + } + + if (i == AR5416_NUM_BAND_EDGES) { + if (f > edges[i - 1].channel && + edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { + /* lower channel has the inband flag set */ + rc = edges[i - 1].power_flags & + ~AR9170_CALCTL_EDGE_FLAGS; + } + } + return rc; +} + +static u8 ar9170_get_heavy_clip(struct ar9170 *ar, + struct ar9170_calctl_edges edges[], + u32 freq, enum ar9170_bw bw) +{ + u8 f; + int i; + u8 rc = 0; + + if (freq < 3000) + f = freq - 2300; + else + f = (freq - 4800) / 5; + + if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) + rc |= 0xf0; + + for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { + if (edges[i].channel == 0xff) + break; + if (f == edges[i].channel) { + if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) + rc |= 0x0f; + break; + } + } + + return rc; +} + +/* + * calculate the conformance test limits and the heavy clip parameter + * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) + */ +static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) +{ + u8 ctl_grp; /* CTL group */ + u8 ctl_idx; /* CTL index */ + int i, j; + struct ctl_modes { + u8 ctl_mode; + u8 max_power; + u8 *pwr_cal_data; + int pwr_cal_len; + } *modes; + + /* + * order is relevant in the mode_list_*: we fall back to the + * lower indices if any mode is missed in the EEPROM. + */ + struct ctl_modes mode_list_2ghz[] = { + { CTL_11B, 0, ar->power_2G_cck, 4 }, + { CTL_11G, 0, ar->power_2G_ofdm, 4 }, + { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, + { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, + }; + struct ctl_modes mode_list_5ghz[] = { + { CTL_11A, 0, ar->power_5G_leg, 4 }, + { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, + { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, + }; + int nr_modes; + +#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) + + ar->phy_heavy_clip = 0; + + /* + * TODO: investigate the differences between OTUS' + * hpreg.c::zfHpGetRegulatoryDomain() and + * ath/regd.c::ath_regd_get_band_ctl() - + * e.g. for FCC3_WORLD the OTUS procedure + * always returns CTL_FCC, while the one in ath/ delivers + * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. + */ + ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, + ar->hw->conf.channel->band); + + /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ + if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) + ctl_grp = CTL_FCC; + + if (ctl_grp != CTL_FCC) + /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ + return; + + if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { + modes = mode_list_2ghz; + nr_modes = ARRAY_SIZE(mode_list_2ghz); + } else { + modes = mode_list_5ghz; + nr_modes = ARRAY_SIZE(mode_list_5ghz); + } + + for (i = 0; i < nr_modes; i++) { + u8 c = ctl_grp | modes[i].ctl_mode; + for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) + if (c == ar->eeprom.ctl_index[ctl_idx]) + break; + if (ctl_idx < AR5416_NUM_CTLS) { + int f_off = 0; + + /* determine heav clip parameter from + the 11G edges array */ + if (modes[i].ctl_mode == CTL_11G) { + ar->phy_heavy_clip = + ar9170_get_heavy_clip(ar, + EDGES(ctl_idx, 1), + freq, bw); + } + + /* adjust freq for 40MHz */ + if (modes[i].ctl_mode == CTL_2GHT40 || + modes[i].ctl_mode == CTL_5GHT40) { + if (bw == AR9170_BW_40_BELOW) + f_off = -10; + else + f_off = 10; + } + + modes[i].max_power = + ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), + freq+f_off); + + /* + * TODO: check if the regulatory max. power is + * controlled by cfg80211 for DFS + * (hpmain applies it to max_power itself for DFS freq) + */ + + } else { + /* + * Workaround in otus driver, hpmain.c, line 3906: + * if no data for 5GHT20 are found, take the + * legacy 5G value. + * We extend this here to fallback from any other *HT or + * 11G, too. + */ + int k = i; + + modes[i].max_power = AR5416_MAX_RATE_POWER; + while (k-- > 0) { + if (modes[k].max_power != + AR5416_MAX_RATE_POWER) { + modes[i].max_power = modes[k].max_power; + break; + } + } + } + + /* apply max power to pwr_cal_data (ar->power_*) */ + for (j = 0; j < modes[i].pwr_cal_len; j++) { + modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], + modes[i].max_power); + } + } + + if (ar->phy_heavy_clip & 0xf0) { + ar->power_2G_ht40[0]--; + ar->power_2G_ht40[1]--; + ar->power_2G_ht40[2]--; + } + if (ar->phy_heavy_clip & 0xf) { + ar->power_2G_ht20[0]++; + ar->power_2G_ht20[1]++; + ar->power_2G_ht20[2]++; + } + + +#undef EDGES +} + +static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) +{ + struct ar9170_calibration_target_power_legacy *ctpl; + struct ar9170_calibration_target_power_ht *ctph; + u8 *ctpres; + int ntargets; + int idx, i, n; + u8 ackpower, ackchains, f; + u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; + + if (freq < 3000) + f = freq - 2300; + else + f = (freq - 4800)/5; + + /* + * cycle through the various modes + * + * legacy modes first: 5G, 2G CCK, 2G OFDM + */ + for (i = 0; i < 3; i++) { + switch (i) { + case 0: /* 5 GHz legacy */ + ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_leg; + break; + case 1: /* 2.4 GHz CCK */ + ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; + ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; + ctpres = ar->power_2G_cck; + break; + case 2: /* 2.4 GHz OFDM */ + ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ofdm; + break; + default: + BUG(); + } + + for (n = 0; n < ntargets; n++) { + if (ctpl[n].freq == 0xff) + break; + pwr_freqs[n] = ctpl[n].freq; + } + ntargets = n; + idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); + for (n = 0; n < 4; n++) + ctpres[n] = ar9170_interpolate_u8( + f, + ctpl[idx + 0].freq, + ctpl[idx + 0].power[n], + ctpl[idx + 1].freq, + ctpl[idx + 1].power[n]); + } + + /* + * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 + */ + for (i = 0; i < 4; i++) { + switch (i) { + case 0: /* 5 GHz HT 20 */ + ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_ht20; + break; + case 1: /* 5 GHz HT 40 */ + ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_ht40; + break; + case 2: /* 2.4 GHz HT 20 */ + ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ht20; + break; + case 3: /* 2.4 GHz HT 40 */ + ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ht40; + break; + default: + BUG(); + } + + for (n = 0; n < ntargets; n++) { + if (ctph[n].freq == 0xff) + break; + pwr_freqs[n] = ctph[n].freq; + } + ntargets = n; + idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); + for (n = 0; n < 8; n++) + ctpres[n] = ar9170_interpolate_u8( + f, + ctph[idx + 0].freq, + ctph[idx + 0].power[n], + ctph[idx + 1].freq, + ctph[idx + 1].power[n]); + } + + + /* calc. conformance test limits and apply to ar->power*[] */ + ar9170_calc_ctl(ar, freq, bw); + + /* set ACK/CTS TX power */ + ar9170_regwrite_begin(ar); + + if (ar->eeprom.tx_mask != 1) + ackchains = AR9170_TX_PHY_TXCHAIN_2; + else + ackchains = AR9170_TX_PHY_TXCHAIN_1; + + if (freq < 3000) + ackpower = ar->power_2G_ofdm[0] & 0x3f; + else + ackpower = ar->power_5G_leg[0] & 0x3f; + + ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); + ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | + ackpower << 21 | ackchains << 27); + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +static int ar9170_calc_noise_dbm(u32 raw_noise) +{ + if (raw_noise & 0x100) + return ~((raw_noise & 0x0ff) >> 1); + else + return (raw_noise & 0xff) >> 1; +} + +int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, + enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) +{ + const struct ar9170_phy_freq_params *freqpar; + u32 cmd, tmp, offs; + __le32 vals[8]; + int i, err; + bool bandswitch; + + /* clear BB heavy clip enable */ + err = ar9170_write_reg(ar, 0x1c59e0, 0x200); + if (err) + return err; + + /* may be NULL at first setup */ + if (ar->channel) + bandswitch = ar->channel->band != channel->band; + else + bandswitch = true; + + /* HW workaround */ + if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && + channel->center_freq <= 2417) + bandswitch = true; + + err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); + if (err) + return err; + + if (rfi != AR9170_RFI_NONE || bandswitch) { + u32 val = 0x400; + + if (rfi == AR9170_RFI_COLD) + val = 0x800; + + /* warm/cold reset BB/ADDA */ + err = ar9170_write_reg(ar, 0x1d4004, val); + if (err) + return err; + + err = ar9170_write_reg(ar, 0x1d4004, 0x0); + if (err) + return err; + + err = ar9170_init_phy(ar, channel->band); + if (err) + return err; + + err = ar9170_init_rf_banks_0_7(ar, + channel->band == IEEE80211_BAND_5GHZ); + if (err) + return err; + + cmd = AR9170_CMD_RF_INIT; + } else { + cmd = AR9170_CMD_FREQUENCY; + } + + err = ar9170_init_rf_bank4_pwr(ar, + channel->band == IEEE80211_BAND_5GHZ, + channel->center_freq, bw); + if (err) + return err; + + switch (bw) { + case AR9170_BW_20: + tmp = 0x240; + offs = 0; + break; + case AR9170_BW_40_BELOW: + tmp = 0x2c4; + offs = 3; + break; + case AR9170_BW_40_ABOVE: + tmp = 0x2d4; + offs = 1; + break; + default: + BUG(); + return -ENOSYS; + } + + if (ar->eeprom.tx_mask != 1) + tmp |= 0x100; + + err = ar9170_write_reg(ar, 0x1c5804, tmp); + if (err) + return err; + + err = ar9170_set_freq_cal_data(ar, channel); + if (err) + return err; + + err = ar9170_set_power_cal(ar, channel->center_freq, bw); + if (err) + return err; + + freqpar = ar9170_get_hw_dyn_params(channel, bw); + + vals[0] = cpu_to_le32(channel->center_freq * 1000); + vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf)); + vals[2] = cpu_to_le32(offs << 2 | 1); + vals[3] = cpu_to_le32(freqpar->coeff_exp); + vals[4] = cpu_to_le32(freqpar->coeff_man); + vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); + vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); + vals[7] = cpu_to_le32(1000); + + err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, + sizeof(vals), (u8 *)vals); + if (err) + return err; + + if (ar->phy_heavy_clip) { + err = ar9170_write_reg(ar, 0x1c59e0, + 0x200 | ar->phy_heavy_clip); + if (err) { + if (ar9170_nag_limiter(ar)) + wiphy_err(ar->hw->wiphy, + "failed to set heavy clip\n"); + } + } + + for (i = 0; i < 2; i++) { + ar->noise[i] = ar9170_calc_noise_dbm( + (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); + + ar->noise[i + 2] = ar9170_calc_noise_dbm( + (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); + } + + ar->channel = channel; + return 0; +} diff --git a/trunk/drivers/net/wireless/ath/ar9170/usb.c b/trunk/drivers/net/wireless/ath/ar9170/usb.c new file mode 100644 index 000000000000..d3be6f9816b5 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/usb.c @@ -0,0 +1,1008 @@ +/* + * Atheros AR9170 driver + * + * USB - frontend + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ar9170.h" +#include "cmd.h" +#include "hw.h" +#include "usb.h" + +MODULE_AUTHOR("Johannes Berg "); +MODULE_AUTHOR("Christian Lamparter "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); +MODULE_FIRMWARE("ar9170.fw"); + +enum ar9170_requirements { + AR9170_REQ_FW1_ONLY = 1, +}; + +static struct usb_device_id ar9170_usb_ids[] = { + /* Atheros 9170 */ + { USB_DEVICE(0x0cf3, 0x9170) }, + /* Atheros TG121N */ + { USB_DEVICE(0x0cf3, 0x1001) }, + /* TP-Link TL-WN821N v2 */ + { USB_DEVICE(0x0cf3, 0x1002) }, + /* 3Com Dual Band 802.11n USB Adapter */ + { USB_DEVICE(0x0cf3, 0x1010) }, + /* H3C Dual Band 802.11n USB Adapter */ + { USB_DEVICE(0x0cf3, 0x1011) }, + /* Cace Airpcap NX */ + { USB_DEVICE(0xcace, 0x0300) }, + /* D-Link DWA 160 A1 */ + { USB_DEVICE(0x07d1, 0x3c10) }, + /* D-Link DWA 160 A2 */ + { USB_DEVICE(0x07d1, 0x3a09) }, + /* Netgear WNA1000 */ + { USB_DEVICE(0x0846, 0x9040) }, + /* Netgear WNDA3100 */ + { USB_DEVICE(0x0846, 0x9010) }, + /* Netgear WN111 v2 */ + { USB_DEVICE(0x0846, 0x9001) }, + /* Zydas ZD1221 */ + { USB_DEVICE(0x0ace, 0x1221) }, + /* Proxim ORiNOCO 802.11n USB */ + { USB_DEVICE(0x1435, 0x0804) }, + /* WNC Generic 11n USB Dongle */ + { USB_DEVICE(0x1435, 0x0326) }, + /* ZyXEL NWD271N */ + { USB_DEVICE(0x0586, 0x3417) }, + /* Z-Com UB81 BG */ + { USB_DEVICE(0x0cde, 0x0023) }, + /* Z-Com UB82 ABG */ + { USB_DEVICE(0x0cde, 0x0026) }, + /* Sphairon Homelink 1202 */ + { USB_DEVICE(0x0cde, 0x0027) }, + /* Arcadyan WN7512 */ + { USB_DEVICE(0x083a, 0xf522) }, + /* Planex GWUS300 */ + { USB_DEVICE(0x2019, 0x5304) }, + /* IO-Data WNGDNUS2 */ + { USB_DEVICE(0x04bb, 0x093f) }, + /* AVM FRITZ!WLAN USB Stick N */ + { USB_DEVICE(0x057C, 0x8401) }, + /* NEC WL300NU-G */ + { USB_DEVICE(0x0409, 0x0249) }, + /* AVM FRITZ!WLAN USB Stick N 2.4 */ + { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, + /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ + { USB_DEVICE(0x1668, 0x1200) }, + + /* terminate */ + {} +}; +MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); + +static void ar9170_usb_submit_urb(struct ar9170_usb *aru) +{ + struct urb *urb; + unsigned long flags; + int err; + + if (unlikely(!IS_STARTED(&aru->common))) + return ; + + spin_lock_irqsave(&aru->tx_urb_lock, flags); + if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { + spin_unlock_irqrestore(&aru->tx_urb_lock, flags); + return ; + } + atomic_inc(&aru->tx_submitted_urbs); + + urb = usb_get_from_anchor(&aru->tx_pending); + if (!urb) { + atomic_dec(&aru->tx_submitted_urbs); + spin_unlock_irqrestore(&aru->tx_urb_lock, flags); + + return ; + } + spin_unlock_irqrestore(&aru->tx_urb_lock, flags); + + aru->tx_pending_urbs--; + usb_anchor_urb(urb, &aru->tx_submitted); + + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err)) { + if (ar9170_nag_limiter(&aru->common)) + dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", + err); + + usb_unanchor_urb(urb); + atomic_dec(&aru->tx_submitted_urbs); + ar9170_tx_callback(&aru->common, urb->context); + } + + usb_free_urb(urb); +} + +static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) +{ + struct sk_buff *skb = urb->context; + struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + + if (unlikely(!aru)) { + dev_kfree_skb_irq(skb); + return ; + } + + atomic_dec(&aru->tx_submitted_urbs); + + ar9170_tx_callback(&aru->common, skb); + + ar9170_usb_submit_urb(aru); +} + +static void ar9170_usb_tx_urb_complete(struct urb *urb) +{ +} + +static void ar9170_usb_irq_completed(struct urb *urb) +{ + struct ar9170_usb *aru = urb->context; + + switch (urb->status) { + /* everything is fine */ + case 0: + break; + + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + + default: + goto resubmit; + } + + ar9170_handle_command_response(&aru->common, urb->transfer_buffer, + urb->actual_length); + +resubmit: + usb_anchor_urb(urb, &aru->rx_submitted); + if (usb_submit_urb(urb, GFP_ATOMIC)) { + usb_unanchor_urb(urb); + goto free; + } + + return; + +free: + usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); +} + +static void ar9170_usb_rx_completed(struct urb *urb) +{ + struct sk_buff *skb = urb->context; + struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + int err; + + if (!aru) + goto free; + + switch (urb->status) { + /* everything is fine */ + case 0: + break; + + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + + default: + goto resubmit; + } + + skb_put(skb, urb->actual_length); + ar9170_rx(&aru->common, skb); + +resubmit: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err)) { + usb_unanchor_urb(urb); + goto free; + } + + return ; + +free: + dev_kfree_skb_irq(skb); +} + +static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, + struct urb *urb, gfp_t gfp) +{ + struct sk_buff *skb; + + skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); + if (!skb) + return -ENOMEM; + + /* reserve some space for mac80211's radiotap */ + skb_reserve(skb, 32); + + usb_fill_bulk_urb(urb, aru->udev, + usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), + skb->data, min(skb_tailroom(skb), + AR9170_MAX_RX_BUFFER_SIZE), + ar9170_usb_rx_completed, skb); + + return 0; +} + +static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) +{ + struct urb *urb = NULL; + void *ibuf; + int err = -ENOMEM; + + /* initialize interrupt endpoint */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto out; + + ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); + if (!ibuf) + goto out; + + usb_fill_int_urb(urb, aru->udev, + usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, + 64, ar9170_usb_irq_completed, aru, 1); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + usb_unanchor_urb(urb); + usb_free_coherent(aru->udev, 64, urb->transfer_buffer, + urb->transfer_dma); + } + +out: + usb_free_urb(urb); + return err; +} + +static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) +{ + struct urb *urb; + int i; + int err = -EINVAL; + + for (i = 0; i < AR9170_NUM_RX_URBS; i++) { + err = -ENOMEM; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto err_out; + + err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); + if (err) { + usb_free_urb(urb); + goto err_out; + } + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + usb_unanchor_urb(urb); + dev_kfree_skb_any((void *) urb->transfer_buffer); + usb_free_urb(urb); + goto err_out; + } + usb_free_urb(urb); + } + + /* the device now waiting for a firmware. */ + aru->common.state = AR9170_IDLE; + return 0; + +err_out: + + usb_kill_anchored_urbs(&aru->rx_submitted); + return err; +} + +static int ar9170_usb_flush(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + struct urb *urb; + int ret, err = 0; + + if (IS_STARTED(ar)) + aru->common.state = AR9170_IDLE; + + usb_wait_anchor_empty_timeout(&aru->tx_pending, + msecs_to_jiffies(800)); + while ((urb = usb_get_from_anchor(&aru->tx_pending))) { + ar9170_tx_callback(&aru->common, (void *) urb->context); + usb_free_urb(urb); + } + + /* lets wait a while until the tx - queues are dried out */ + ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, + msecs_to_jiffies(100)); + if (ret == 0) + err = -ETIMEDOUT; + + usb_kill_anchored_urbs(&aru->tx_submitted); + + if (IS_ACCEPTING_CMD(ar)) + aru->common.state = AR9170_STARTED; + + return err; +} + +static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) +{ + int err; + + aru->common.state = AR9170_UNKNOWN_STATE; + + err = ar9170_usb_flush(&aru->common); + if (err) + dev_err(&aru->udev->dev, "stuck tx urbs!\n"); + + usb_poison_anchored_urbs(&aru->tx_submitted); + usb_poison_anchored_urbs(&aru->rx_submitted); +} + +static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, + unsigned int plen, void *payload, + unsigned int outlen, void *out) +{ + struct ar9170_usb *aru = (void *) ar; + struct urb *urb = NULL; + unsigned long flags; + int err = -ENOMEM; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return -EPERM; + + if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) + return -EINVAL; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (unlikely(!urb)) + goto err_free; + + ar->cmdbuf[0] = cpu_to_le32(plen); + ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); + /* writing multiple regs fills this buffer already */ + if (plen && payload != (u8 *)(&ar->cmdbuf[1])) + memcpy(&ar->cmdbuf[1], payload, plen); + + spin_lock_irqsave(&aru->common.cmdlock, flags); + aru->readbuf = (u8 *)out; + aru->readlen = outlen; + spin_unlock_irqrestore(&aru->common.cmdlock, flags); + + usb_fill_int_urb(urb, aru->udev, + usb_sndintpipe(aru->udev, AR9170_EP_CMD), + aru->common.cmdbuf, plen + 4, + ar9170_usb_tx_urb_complete, NULL, 1); + + usb_anchor_urb(urb, &aru->tx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err)) { + usb_unanchor_urb(urb); + usb_free_urb(urb); + goto err_unbuf; + } + usb_free_urb(urb); + + err = wait_for_completion_timeout(&aru->cmd_wait, HZ); + if (err == 0) { + err = -ETIMEDOUT; + goto err_unbuf; + } + + if (aru->readlen != outlen) { + err = -EMSGSIZE; + goto err_unbuf; + } + + return 0; + +err_unbuf: + /* Maybe the device was removed in the second we were waiting? */ + if (IS_STARTED(ar)) { + dev_err(&aru->udev->dev, "no command feedback " + "received (%d).\n", err); + + /* provide some maybe useful debug information */ + print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, + aru->common.cmdbuf, plen + 4); + dump_stack(); + } + + /* invalidate to avoid completing the next prematurely */ + spin_lock_irqsave(&aru->common.cmdlock, flags); + aru->readbuf = NULL; + aru->readlen = 0; + spin_unlock_irqrestore(&aru->common.cmdlock, flags); + +err_free: + + return err; +} + +static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_usb *aru = (struct ar9170_usb *) ar; + struct urb *urb; + + if (unlikely(!IS_STARTED(ar))) { + /* Seriously, what were you drink... err... thinking!? */ + return -EPERM; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (unlikely(!urb)) + return -ENOMEM; + + usb_fill_bulk_urb(urb, aru->udev, + usb_sndbulkpipe(aru->udev, AR9170_EP_TX), + skb->data, skb->len, + ar9170_usb_tx_urb_complete_frame, skb); + urb->transfer_flags |= URB_ZERO_PACKET; + + usb_anchor_urb(urb, &aru->tx_pending); + aru->tx_pending_urbs++; + + usb_free_urb(urb); + + ar9170_usb_submit_urb(aru); + return 0; +} + +static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) +{ + struct ar9170_usb *aru = (void *) ar; + unsigned long flags; + u32 in, out; + + if (unlikely(!buffer)) + return ; + + in = le32_to_cpup((__le32 *)buffer); + out = le32_to_cpu(ar->cmdbuf[0]); + + /* mask off length byte */ + out &= ~0xFF; + + if (aru->readlen >= 0) { + /* add expected length */ + out |= aru->readlen; + } else { + /* add obtained length */ + out |= in & 0xFF; + } + + /* + * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response + * length and we cannot predict the correct length in advance. + * So we only check if we provided enough space for the data. + */ + if (unlikely(out < in)) { + dev_warn(&aru->udev->dev, "received invalid command response " + "got %d bytes, instead of %d bytes " + "and the resp length is %d bytes\n", + in, out, len); + print_hex_dump_bytes("ar9170 invalid resp: ", + DUMP_PREFIX_OFFSET, buffer, len); + /* + * Do not complete, then the command times out, + * and we get a stack trace from there. + */ + return ; + } + + spin_lock_irqsave(&aru->common.cmdlock, flags); + if (aru->readbuf && len > 0) { + memcpy(aru->readbuf, buffer + 4, len - 4); + aru->readbuf = NULL; + } + complete(&aru->cmd_wait); + spin_unlock_irqrestore(&aru->common.cmdlock, flags); +} + +static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, + size_t len, u32 addr, bool complete) +{ + int transfer, err; + u8 *buf = kmalloc(4096, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + while (len) { + transfer = min_t(int, len, 4096); + memcpy(buf, data, transfer); + + err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), + 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, + addr >> 8, 0, buf, transfer, 1000); + + if (err < 0) { + kfree(buf); + return err; + } + + len -= transfer; + data += transfer; + addr += transfer; + } + kfree(buf); + + if (complete) { + err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), + 0x31 /* FW DL COMPLETE */, + 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); + } + + return 0; +} + +static int ar9170_usb_reset(struct ar9170_usb *aru) +{ + int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); + + if (lock) { + ret = usb_lock_device_for_reset(aru->udev, aru->intf); + if (ret < 0) { + dev_err(&aru->udev->dev, "unable to lock device " + "for reset (%d).\n", ret); + return ret; + } + } + + ret = usb_reset_device(aru->udev); + if (lock) + usb_unlock_device(aru->udev); + + /* let it rest - for a second - */ + msleep(1000); + + return ret; +} + +static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) +{ + int err; + + if (!aru->init_values) + goto upload_fw_start; + + /* First, upload initial values to device RAM */ + err = ar9170_usb_upload(aru, aru->init_values->data, + aru->init_values->size, 0x102800, false); + if (err) { + dev_err(&aru->udev->dev, "firmware part 1 " + "upload failed (%d).\n", err); + return err; + } + +upload_fw_start: + + /* Then, upload the firmware itself and start it */ + return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, + 0x200000, true); +} + +static int ar9170_usb_init_transport(struct ar9170_usb *aru) +{ + struct ar9170 *ar = (void *) &aru->common; + int err; + + ar9170_regwrite_begin(ar); + + /* Set USB Rx stream mode MAX packet number to 2 */ + ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); + + /* Set USB Rx stream mode timeout to 10us */ + ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); + + ar9170_regwrite_finish(); + + err = ar9170_regwrite_result(); + if (err) + dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); + + return err; +} + +static void ar9170_usb_stop(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + int ret; + + if (IS_ACCEPTING_CMD(ar)) + aru->common.state = AR9170_STOPPED; + + ret = ar9170_usb_flush(ar); + if (ret) + dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); + + usb_poison_anchored_urbs(&aru->tx_submitted); + + /* + * Note: + * So far we freed all tx urbs, but we won't dare to touch any rx urbs. + * Else we would end up with a unresponsive device... + */ +} + +static int ar9170_usb_open(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + int err; + + usb_unpoison_anchored_urbs(&aru->tx_submitted); + err = ar9170_usb_init_transport(aru); + if (err) { + usb_poison_anchored_urbs(&aru->tx_submitted); + return err; + } + + aru->common.state = AR9170_IDLE; + return 0; +} + +static int ar9170_usb_init_device(struct ar9170_usb *aru) +{ + int err; + + err = ar9170_usb_alloc_rx_irq_urb(aru); + if (err) + goto err_out; + + err = ar9170_usb_alloc_rx_bulk_urbs(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_upload_firmware(aru); + if (err) { + err = ar9170_echo_test(&aru->common, 0x60d43110); + if (err) { + /* force user invention, by disabling the device */ + err = usb_driver_set_configuration(aru->udev, -1); + dev_err(&aru->udev->dev, "device is in a bad state. " + "please reconnect it!\n"); + goto err_unrx; + } + } + + return 0; + +err_unrx: + ar9170_usb_cancel_urbs(aru); + +err_out: + return err; +} + +static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) +{ + struct device *parent = aru->udev->dev.parent; + struct usb_device *udev; + + /* + * Store a copy of the usb_device pointer locally. + * This is because device_release_driver initiates + * ar9170_usb_disconnect, which in turn frees our + * driver context (aru). + */ + udev = aru->udev; + + complete(&aru->firmware_loading_complete); + + /* unbind anything failed */ + if (parent) + device_lock(parent); + + device_release_driver(&udev->dev); + if (parent) + device_unlock(parent); + + usb_put_dev(udev); +} + +static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) +{ + struct ar9170_usb *aru = context; + int err; + + aru->firmware = fw; + + if (!fw) { + dev_err(&aru->udev->dev, "firmware file not found.\n"); + goto err_freefw; + } + + err = ar9170_usb_init_device(aru); + if (err) + goto err_freefw; + + err = ar9170_usb_open(&aru->common); + if (err) + goto err_unrx; + + err = ar9170_register(&aru->common, &aru->udev->dev); + + ar9170_usb_stop(&aru->common); + if (err) + goto err_unrx; + + complete(&aru->firmware_loading_complete); + usb_put_dev(aru->udev); + return; + + err_unrx: + ar9170_usb_cancel_urbs(aru); + + err_freefw: + ar9170_usb_firmware_failed(aru); +} + +static void ar9170_usb_firmware_inits(const struct firmware *fw, + void *context) +{ + struct ar9170_usb *aru = context; + int err; + + if (!fw) { + dev_err(&aru->udev->dev, "file with init values not found.\n"); + ar9170_usb_firmware_failed(aru); + return; + } + + aru->init_values = fw; + + /* ok so we have the init values -- get code for two-stage */ + + err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_finish); + if (err) + ar9170_usb_firmware_failed(aru); +} + +static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) +{ + struct ar9170_usb *aru = context; + int err; + + if (fw) { + ar9170_usb_firmware_finish(fw, context); + return; + } + + if (aru->req_one_stage_fw) { + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found and is required for this device\n"); + ar9170_usb_firmware_failed(aru); + return; + } + + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found, trying old firmware...\n"); + + err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_inits); + if (err) + ar9170_usb_firmware_failed(aru); +} + +static bool ar9170_requires_one_stage(const struct usb_device_id *id) +{ + if (!id->driver_info) + return false; + if (id->driver_info == AR9170_REQ_FW1_ONLY) + return true; + return false; +} + +static int ar9170_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct ar9170_usb *aru; + struct ar9170 *ar; + struct usb_device *udev; + int err; + + aru = ar9170_alloc(sizeof(*aru)); + if (IS_ERR(aru)) { + err = PTR_ERR(aru); + goto out; + } + + udev = interface_to_usbdev(intf); + usb_get_dev(udev); + aru->udev = udev; + aru->intf = intf; + ar = &aru->common; + + aru->req_one_stage_fw = ar9170_requires_one_stage(id); + + usb_set_intfdata(intf, aru); + SET_IEEE80211_DEV(ar->hw, &intf->dev); + + init_usb_anchor(&aru->rx_submitted); + init_usb_anchor(&aru->tx_pending); + init_usb_anchor(&aru->tx_submitted); + init_completion(&aru->cmd_wait); + init_completion(&aru->firmware_loading_complete); + spin_lock_init(&aru->tx_urb_lock); + + aru->tx_pending_urbs = 0; + atomic_set(&aru->tx_submitted_urbs, 0); + + aru->common.stop = ar9170_usb_stop; + aru->common.flush = ar9170_usb_flush; + aru->common.open = ar9170_usb_open; + aru->common.tx = ar9170_usb_tx; + aru->common.exec_cmd = ar9170_usb_exec_cmd; + aru->common.callback_cmd = ar9170_usb_callback_cmd; + +#ifdef CONFIG_PM + udev->reset_resume = 1; +#endif /* CONFIG_PM */ + err = ar9170_usb_reset(aru); + if (err) + goto err_freehw; + + usb_get_dev(aru->udev); + return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_step2); +err_freehw: + usb_set_intfdata(intf, NULL); + usb_put_dev(udev); + ieee80211_free_hw(ar->hw); +out: + return err; +} + +static void ar9170_usb_disconnect(struct usb_interface *intf) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + + if (!aru) + return; + + aru->common.state = AR9170_IDLE; + + wait_for_completion(&aru->firmware_loading_complete); + + ar9170_unregister(&aru->common); + ar9170_usb_cancel_urbs(aru); + + usb_put_dev(aru->udev); + usb_set_intfdata(intf, NULL); + ieee80211_free_hw(aru->common.hw); + + release_firmware(aru->init_values); + release_firmware(aru->firmware); +} + +#ifdef CONFIG_PM +static int ar9170_suspend(struct usb_interface *intf, + pm_message_t message) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + + if (!aru) + return -ENODEV; + + aru->common.state = AR9170_IDLE; + ar9170_usb_cancel_urbs(aru); + + return 0; +} + +static int ar9170_resume(struct usb_interface *intf) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + int err; + + if (!aru) + return -ENODEV; + + usb_unpoison_anchored_urbs(&aru->rx_submitted); + usb_unpoison_anchored_urbs(&aru->tx_submitted); + + err = ar9170_usb_init_device(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_open(&aru->common); + if (err) + goto err_unrx; + + return 0; + +err_unrx: + aru->common.state = AR9170_IDLE; + ar9170_usb_cancel_urbs(aru); + + return err; +} +#endif /* CONFIG_PM */ + +static struct usb_driver ar9170_driver = { + .name = "ar9170usb", + .probe = ar9170_usb_probe, + .disconnect = ar9170_usb_disconnect, + .id_table = ar9170_usb_ids, + .soft_unbind = 1, +#ifdef CONFIG_PM + .suspend = ar9170_suspend, + .resume = ar9170_resume, + .reset_resume = ar9170_resume, +#endif /* CONFIG_PM */ +}; + +static int __init ar9170_init(void) +{ + return usb_register(&ar9170_driver); +} + +static void __exit ar9170_exit(void) +{ + usb_deregister(&ar9170_driver); +} + +module_init(ar9170_init); +module_exit(ar9170_exit); diff --git a/trunk/drivers/net/wireless/ath/ar9170/usb.h b/trunk/drivers/net/wireless/ath/ar9170/usb.h new file mode 100644 index 000000000000..919b06046eb3 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ar9170/usb.h @@ -0,0 +1,82 @@ +/* + * Atheros AR9170 USB driver + * + * Driver specific definitions + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __USB_H +#define __USB_H + +#include +#include +#include +#include +#include +#include +#include +#include "eeprom.h" +#include "hw.h" +#include "ar9170.h" + +#define AR9170_NUM_RX_URBS 16 +#define AR9170_NUM_TX_URBS 8 + +struct firmware; + +struct ar9170_usb { + struct ar9170 common; + struct usb_device *udev; + struct usb_interface *intf; + + struct usb_anchor rx_submitted; + struct usb_anchor tx_pending; + struct usb_anchor tx_submitted; + + bool req_one_stage_fw; + + spinlock_t tx_urb_lock; + atomic_t tx_submitted_urbs; + unsigned int tx_pending_urbs; + + struct completion cmd_wait; + struct completion firmware_loading_complete; + int readlen; + u8 *readbuf; + + const struct firmware *init_values; + const struct firmware *firmware; +}; + +#endif /* __USB_H */ diff --git a/trunk/drivers/net/wireless/ath/ath.h b/trunk/drivers/net/wireless/ath/ath.h index 7cf4317a2a84..a6c6a466000f 100644 --- a/trunk/drivers/net/wireless/ath/ath.h +++ b/trunk/drivers/net/wireless/ath/ath.h @@ -119,11 +119,17 @@ struct ath_ops { void (*write)(void *, u32 val, u32 reg_offset); void (*enable_write_buffer)(void *); void (*write_flush) (void *); - u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); }; struct ath_common; -struct ath_bus_ops; + +struct ath_bus_ops { + enum ath_bus_type ath_bus_type; + void (*read_cachesize)(struct ath_common *common, int *csz); + bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); + void (*bt_coex_prep)(struct ath_common *common); + void (*extn_synch_en)(struct ath_common *common); +}; struct ath_common { void *ah; diff --git a/trunk/drivers/net/wireless/ath/ath5k/ahb.c b/trunk/drivers/net/wireless/ath/ath5k/ahb.c index ea9982781559..82324e98efef 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath5k/ahb.c @@ -18,7 +18,6 @@ #include #include -#include #include #include "ath5k.h" #include "debug.h" @@ -63,27 +62,10 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) return 0; } -static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) -{ - struct ath5k_softc *sc = ah->ah_sc; - struct platform_device *pdev = to_platform_device(sc->dev); - struct ar231x_board_config *bcfg = pdev->dev.platform_data; - u8 *cfg_mac; - - if (to_platform_device(sc->dev)->id == 0) - cfg_mac = bcfg->config->wlan0_mac; - else - cfg_mac = bcfg->config->wlan1_mac; - - memcpy(mac, cfg_mac, ETH_ALEN); - return 0; -} - static const struct ath_bus_ops ath_ahb_bus_ops = { .ath_bus_type = ATH_AHB, .read_cachesize = ath5k_ahb_read_cachesize, .eeprom_read = ath5k_ahb_eeprom_read, - .eeprom_read_mac = ath5k_ahb_eeprom_read_mac, }; /*Initialization*/ @@ -160,16 +142,6 @@ static int ath_ahb_probe(struct platform_device *pdev) else reg |= AR5K_AR5312_ENABLE_WLAN1; __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); - - /* - * On a dual-band AR5312, the multiband radio is only - * used as pass-through. Disable 2 GHz support in the - * driver for it - */ - if (to_platform_device(sc->dev)->id == 0 && - (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) == - (BD_WLAN1|BD_WLAN0)) - __set_bit(ATH_STAT_2G_DISABLED, sc->status); } ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); diff --git a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h index bb50700436fe..8a06dbd39629 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h @@ -224,7 +224,8 @@ /* SIFS */ #define AR5K_INIT_SIFS_TURBO 6 -#define AR5K_INIT_SIFS_DEFAULT_BG 10 +/* XXX: 8 from initvals 10 from standard */ +#define AR5K_INIT_SIFS_DEFAULT_BG 8 #define AR5K_INIT_SIFS_DEFAULT_A 16 #define AR5K_INIT_SIFS_HALF_RATE 32 #define AR5K_INIT_SIFS_QUARTER_RATE 64 @@ -452,10 +453,12 @@ struct ath5k_tx_status { u16 ts_seqnum; u16 ts_tstamp; u8 ts_status; + u8 ts_rate[4]; + u8 ts_retry[4]; u8 ts_final_idx; - u8 ts_final_retry; s8 ts_rssi; u8 ts_shortretry; + u8 ts_longretry; u8 ts_virtcol; u8 ts_antenna; }; @@ -872,19 +875,6 @@ enum ath5k_int { AR5K_INT_QTRIG = 0x40000000, /* Non common */ AR5K_INT_GLOBAL = 0x80000000, - AR5K_INT_TX_ALL = AR5K_INT_TXOK - | AR5K_INT_TXDESC - | AR5K_INT_TXERR - | AR5K_INT_TXEOL - | AR5K_INT_TXURN, - - AR5K_INT_RX_ALL = AR5K_INT_RXOK - | AR5K_INT_RXDESC - | AR5K_INT_RXERR - | AR5K_INT_RXNOFRM - | AR5K_INT_RXEOL - | AR5K_INT_RXORN, - AR5K_INT_COMMON = AR5K_INT_RXOK | AR5K_INT_RXDESC | AR5K_INT_RXERR @@ -1068,7 +1058,6 @@ struct ath5k_hw { u8 ah_coverage_class; bool ah_ack_bitrate_high; u8 ah_bwmode; - bool ah_short_slot; /* Antenna Control */ u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; @@ -1155,13 +1144,6 @@ struct ath5k_hw { struct ath5k_rx_status *); }; -struct ath_bus_ops { - enum ath_bus_type ath_bus_type; - void (*read_cachesize)(struct ath_common *common, int *csz); - bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); - int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac); -}; - /* * Prototypes */ @@ -1245,12 +1227,13 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah); /* EEPROM access functions */ int ath5k_eeprom_init(struct ath5k_hw *ah); void ath5k_eeprom_detach(struct ath5k_hw *ah); +int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); /* Protocol Control Unit Functions */ /* Helpers */ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, - int len, struct ieee80211_rate *rate, bool shortpre); + int len, struct ieee80211_rate *rate); unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); diff --git a/trunk/drivers/net/wireless/ath/ath5k/attach.c b/trunk/drivers/net/wireless/ath/ath5k/attach.c index 1588401de3c4..bc8240560488 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/attach.c +++ b/trunk/drivers/net/wireless/ath/ath5k/attach.c @@ -313,17 +313,12 @@ int ath5k_hw_init(struct ath5k_softc *sc) goto err; } - if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) { - __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); - __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); - } - /* Crypto settings */ common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); if (srev >= AR5K_SREV_AR5212_V4 && - (ee->ee_version < AR5K_EEPROM_VERSION_5_0 || + (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index 7583841fc29a..4d7f21ee111c 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -1443,21 +1443,6 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) return true; } -static void -ath5k_set_current_imask(struct ath5k_softc *sc) -{ - enum ath5k_int imask = sc->imask; - unsigned long flags; - - spin_lock_irqsave(&sc->irqlock, flags); - if (sc->rx_pending) - imask &= ~AR5K_INT_RX_ALL; - if (sc->tx_pending) - imask &= ~AR5K_INT_TX_ALL; - ath5k_hw_set_imr(sc->ah, imask); - spin_unlock_irqrestore(&sc->irqlock, flags); -} - static void ath5k_tasklet_rx(unsigned long data) { @@ -1521,8 +1506,6 @@ ath5k_tasklet_rx(unsigned long data) } while (ath5k_rxbuf_setup(sc, bf) == 0); unlock: spin_unlock(&sc->rxbuflock); - sc->rx_pending = false; - ath5k_set_current_imask(sc); } @@ -1590,28 +1573,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, struct ath5k_txq *txq, struct ath5k_tx_status *ts) { struct ieee80211_tx_info *info; - u8 tries[3]; int i; sc->stats.tx_all_count++; sc->stats.tx_bytes_count += skb->len; info = IEEE80211_SKB_CB(skb); - tries[0] = info->status.rates[0].count; - tries[1] = info->status.rates[1].count; - tries[2] = info->status.rates[2].count; - ieee80211_tx_info_clear_status(info); - - for (i = 0; i < ts->ts_final_idx; i++) { + for (i = 0; i < 4; i++) { struct ieee80211_tx_rate *r = &info->status.rates[i]; - r->count = tries[i]; + if (ts->ts_rate[i]) { + r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]); + r->count = ts->ts_retry[i]; + } else { + r->idx = -1; + r->count = 0; + } } - info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry; - info->status.rates[ts->ts_final_idx + 1].idx = -1; + /* count the successful attempt as well */ + info->status.rates[ts->ts_final_idx].count++; if (unlikely(ts->ts_status)) { sc->stats.ack_fail++; @@ -1626,9 +1609,6 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, } else { info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ts->ts_rssi; - - /* count the successful attempt as well */ - info->status.rates[ts->ts_final_idx].count++; } /* @@ -1710,9 +1690,6 @@ ath5k_tasklet_tx(unsigned long data) for (i=0; i < AR5K_NUM_TX_QUEUES; i++) if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) ath5k_tx_processq(sc, &sc->txqs[i]); - - sc->tx_pending = false; - ath5k_set_current_imask(sc); } @@ -2142,20 +2119,6 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ } -static void -ath5k_schedule_rx(struct ath5k_softc *sc) -{ - sc->rx_pending = true; - tasklet_schedule(&sc->rxtq); -} - -static void -ath5k_schedule_tx(struct ath5k_softc *sc) -{ - sc->tx_pending = true; - tasklet_schedule(&sc->txtq); -} - irqreturn_t ath5k_intr(int irq, void *dev_id) { @@ -2198,7 +2161,7 @@ ath5k_intr(int irq, void *dev_id) ieee80211_queue_work(sc->hw, &sc->reset_work); } else - ath5k_schedule_rx(sc); + tasklet_schedule(&sc->rxtq); } else { if (status & AR5K_INT_SWBA) { tasklet_hi_schedule(&sc->beacontq); @@ -2216,10 +2179,10 @@ ath5k_intr(int irq, void *dev_id) ath5k_hw_update_tx_triglevel(ah, true); } if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) - ath5k_schedule_rx(sc); + tasklet_schedule(&sc->rxtq); if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC | AR5K_INT_TXERR | AR5K_INT_TXEOL)) - ath5k_schedule_tx(sc); + tasklet_schedule(&sc->txtq); if (status & AR5K_INT_BMISS) { /* TODO */ } @@ -2238,9 +2201,6 @@ ath5k_intr(int irq, void *dev_id) } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); - if (sc->rx_pending || sc->tx_pending) - ath5k_set_current_imask(sc); - if (unlikely(!counter)) ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); @@ -2612,8 +2572,6 @@ ath5k_init_hw(struct ath5k_softc *sc) static void stop_tasklets(struct ath5k_softc *sc) { - sc->rx_pending = false; - sc->tx_pending = false; tasklet_kill(&sc->rxtq); tasklet_kill(&sc->txtq); tasklet_kill(&sc->calib); @@ -2880,7 +2838,7 @@ ath5k_init(struct ieee80211_hw *hw) INIT_WORK(&sc->reset_work, ath5k_reset_work); INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); - ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); + ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { ATH5K_ERR(sc, "unable to read address from EEPROM\n"); goto err_queues; @@ -2940,6 +2898,7 @@ ath5k_deinit_softc(struct ath5k_softc *sc) * XXX: ??? detach ath5k_hw ??? * Other than that, it's straightforward... */ + ath5k_debug_finish_device(sc); ieee80211_unregister_hw(hw); ath5k_desc_free(sc); ath5k_txq_release(sc); diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.h b/trunk/drivers/net/wireless/ath/ath5k/base.h index b294f3305011..978f1f4ac2f3 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.h +++ b/trunk/drivers/net/wireless/ath/ath5k/base.h @@ -193,13 +193,12 @@ struct ath5k_softc { dma_addr_t desc_daddr; /* DMA (physical) address */ size_t desc_len; /* size of TX/RX descriptors */ - DECLARE_BITMAP(status, 6); + DECLARE_BITMAP(status, 5); #define ATH_STAT_INVALID 0 /* disable hardware accesses */ #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ #define ATH_STAT_PROMISC 2 #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ -#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ struct ieee80211_channel *curchan; /* current h/w channel */ @@ -208,10 +207,6 @@ struct ath5k_softc { enum ath5k_int imask; /* interrupt mask copy */ - spinlock_t irqlock; - bool rx_pending; /* rx tasklet pending */ - bool tx_pending; /* tx tasklet pending */ - u8 lladdr[ETH_ALEN]; u8 bssidmask[ETH_ALEN]; diff --git a/trunk/drivers/net/wireless/ath/ath5k/caps.c b/trunk/drivers/net/wireless/ath/ath5k/caps.c index 7dd88e1c3ff8..f77e8a703c5c 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/caps.c +++ b/trunk/drivers/net/wireless/ath/ath5k/caps.c @@ -94,9 +94,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) } } - if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112) - __clear_bit(AR5K_MODE_11A, caps->cap_mode); - /* Set number of supported TX queues */ if (ah->ah_version == AR5K_AR5210) caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; diff --git a/trunk/drivers/net/wireless/ath/ath5k/debug.c b/trunk/drivers/net/wireless/ath/ath5k/debug.c index 0bf7313b8a17..0230f30e9e9a 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath5k/debug.c @@ -888,38 +888,65 @@ static const struct file_operations fops_queue = { void ath5k_debug_init_device(struct ath5k_softc *sc) { - struct dentry *phydir; - sc->debug.level = ath5k_debug; - phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); - if (!phydir) - return; + sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", + sc->hw->wiphy->debugfsdir); + + sc->debug.debugfs_debug = debugfs_create_file("debug", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_debug); - debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, - &fops_debug); + sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_registers); - debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); + sc->debug.debugfs_beacon = debugfs_create_file("beacon", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_beacon); - debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, - &fops_beacon); + sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, + sc->debug.debugfs_phydir, sc, &fops_reset); - debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); + sc->debug.debugfs_antenna = debugfs_create_file("antenna", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_antenna); - debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, - &fops_antenna); + sc->debug.debugfs_misc = debugfs_create_file("misc", + S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_misc); - debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); + sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, + &fops_frameerrors); - debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, - &fops_frameerrors); + sc->debug.debugfs_ani = debugfs_create_file("ani", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, + &fops_ani); - debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); + sc->debug.debugfs_queue = debugfs_create_file("queue", + S_IWUSR | S_IRUSR, + sc->debug.debugfs_phydir, sc, + &fops_queue); +} - debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, - &fops_queue); +void +ath5k_debug_finish_device(struct ath5k_softc *sc) +{ + debugfs_remove(sc->debug.debugfs_debug); + debugfs_remove(sc->debug.debugfs_registers); + debugfs_remove(sc->debug.debugfs_beacon); + debugfs_remove(sc->debug.debugfs_reset); + debugfs_remove(sc->debug.debugfs_antenna); + debugfs_remove(sc->debug.debugfs_misc); + debugfs_remove(sc->debug.debugfs_frameerrors); + debugfs_remove(sc->debug.debugfs_ani); + debugfs_remove(sc->debug.debugfs_queue); + debugfs_remove(sc->debug.debugfs_phydir); } + /* functions used in other places */ void diff --git a/trunk/drivers/net/wireless/ath/ath5k/debug.h b/trunk/drivers/net/wireless/ath/ath5k/debug.h index 193dd2d4ea3c..b0355aef68d3 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath5k/debug.h @@ -68,6 +68,17 @@ struct ath5k_buf; struct ath5k_dbg_info { unsigned int level; /* debug level */ + /* debugfs entries */ + struct dentry *debugfs_phydir; + struct dentry *debugfs_debug; + struct dentry *debugfs_registers; + struct dentry *debugfs_beacon; + struct dentry *debugfs_reset; + struct dentry *debugfs_antenna; + struct dentry *debugfs_misc; + struct dentry *debugfs_frameerrors; + struct dentry *debugfs_ani; + struct dentry *debugfs_queue; }; /** @@ -129,6 +140,9 @@ enum ath5k_debug_level { void ath5k_debug_init_device(struct ath5k_softc *sc); +void +ath5k_debug_finish_device(struct ath5k_softc *sc); + void ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); @@ -152,6 +166,9 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) static inline void ath5k_debug_init_device(struct ath5k_softc *sc) {} +static inline void +ath5k_debug_finish_device(struct ath5k_softc *sc) {} + static inline void ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} diff --git a/trunk/drivers/net/wireless/ath/ath5k/desc.c b/trunk/drivers/net/wireless/ath/ath5k/desc.c index dd7cd95c364a..16b44ff7dd3e 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/desc.c +++ b/trunk/drivers/net/wireless/ath/ath5k/desc.c @@ -185,12 +185,6 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, struct ath5k_hw_4w_tx_ctl *tx_ctl; unsigned int frame_len; - /* - * Use local variables for these to reduce load/store access on - * uncached memory - */ - u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; /* @@ -214,9 +208,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (tx_power > AR5K_TUNE_MAX_TXPOWER) tx_power = AR5K_TUNE_MAX_TXPOWER; - /* Clear descriptor status area */ - memset(&desc->ud.ds_tx5212.tx_stat, 0, - sizeof(desc->ud.ds_tx5212.tx_stat)); + /* Clear descriptor */ + memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); /* Setup control descriptor */ @@ -228,7 +221,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; + tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ @@ -239,17 +232,21 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; + tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; - txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | - AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); - txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); - txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); - txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + tx_ctl->tx_control_0 |= + AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | + AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); + tx_ctl->tx_control_1 |= AR5K_REG_SM(type, + AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); + tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); + tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; #define _TX_FLAGS(_c, _flag) \ if (flags & AR5K_TXDESC_##_flag) { \ - txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ + tx_ctl->tx_control_##_c |= \ + AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ } _TX_FLAGS(0, CLRDMASK); @@ -265,8 +262,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, * WEP crap */ if (key_index != AR5K_TXKEYIX_INVALID) { - txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - txctl1 |= AR5K_REG_SM(key_index, + tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; + tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); } @@ -277,16 +274,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if ((flags & AR5K_TXDESC_RTSENA) && (flags & AR5K_TXDESC_CTSENA)) return -EINVAL; - txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; - txctl3 |= AR5K_REG_SM(rtscts_rate, + tx_ctl->tx_control_2 |= rtscts_duration & + AR5K_4W_TX_DESC_CTL2_RTS_DURATION; + tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); } - tx_ctl->tx_control_0 = txctl0; - tx_ctl->tx_control_1 = txctl1; - tx_ctl->tx_control_2 = txctl2; - tx_ctl->tx_control_3 = txctl3; - return 0; } @@ -371,7 +364,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); /*TODO: ts->ts_virtcol + test*/ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, @@ -380,6 +373,9 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); ts->ts_antenna = 1; ts->ts_status = 0; + ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, + AR5K_2W_TX_DESC_CTL0_XMIT_RATE); + ts->ts_retry[0] = ts->ts_longretry; ts->ts_final_idx = 0; if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { @@ -405,48 +401,81 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; - u32 txstat0, txstat1; tx_ctl = &desc->ud.ds_tx5212.tx_ctl; tx_status = &desc->ud.ds_tx5212.tx_stat; - txstat1 = ACCESS_ONCE(tx_status->tx_status_1); - /* No frame has been send or error */ - if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE))) + if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) return -EINPROGRESS; - txstat0 = ACCESS_ONCE(tx_status->tx_status_0); - /* * Get descriptor status */ - ts->ts_tstamp = AR5K_REG_MS(txstat0, + ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - ts->ts_shortretry = AR5K_REG_MS(txstat0, + ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_final_retry = AR5K_REG_MS(txstat0, + ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - ts->ts_seqnum = AR5K_REG_MS(txstat1, + ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_SEQ_NUM); - ts->ts_rssi = AR5K_REG_MS(txstat1, + ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - ts->ts_antenna = (txstat1 & + ts->ts_antenna = (tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; ts->ts_status = 0; - ts->ts_final_idx = AR5K_REG_MS(txstat1, + ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); + /* The longretry counter has the number of un-acked retries + * for the final rate. To get the total number of retries + * we have to add the retry counters for the other rates + * as well + */ + ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; + switch (ts->ts_final_idx) { + case 3: + ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); + + ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); + ts->ts_longretry += ts->ts_retry[2]; + /* fall through */ + case 2: + ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); + + ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); + ts->ts_longretry += ts->ts_retry[1]; + /* fall through */ + case 1: + ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); + + ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); + ts->ts_longretry += ts->ts_retry[0]; + /* fall through */ + case 0: + ts->ts_rate[0] = tx_ctl->tx_control_3 & + AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + break; + } + /* TX error */ - if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { - if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) + if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { + if (tx_status->tx_status_0 & + AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) ts->ts_status |= AR5K_TXERR_XRETRY; - if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) + if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) ts->ts_status |= AR5K_TXERR_FIFO; - if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED) + if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) ts->ts_status |= AR5K_TXERR_FILT; } @@ -580,37 +609,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; - u32 rxstat0, rxstat1; rx_status = &desc->ud.ds_rx.rx_stat; - rxstat1 = ACCESS_ONCE(rx_status->rx_status_1); /* No frame received / not ready */ - if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE))) + if (unlikely(!(rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_DONE))) return -EINPROGRESS; memset(rs, 0, sizeof(struct ath5k_rx_status)); - rxstat0 = ACCESS_ONCE(rx_status->rx_status_0); /* * Frame receive status */ - rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; - rs->rs_rssi = AR5K_REG_MS(rxstat0, + rs->rs_datalen = rx_status->rx_status_0 & + AR5K_5212_RX_DESC_STATUS0_DATA_LEN; + rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); - rs->rs_rate = AR5K_REG_MS(rxstat0, + rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rxstat0, + rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); - rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE); - rs->rs_tstamp = AR5K_REG_MS(rxstat1, + rs->rs_more = !!(rx_status->rx_status_0 & + AR5K_5212_RX_DESC_STATUS0_MORE); + rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); /* * Key table status */ - if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) - rs->rs_keyix = AR5K_REG_MS(rxstat1, + if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) + rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); else rs->rs_keyix = AR5K_RXKEYIX_INVALID; @@ -618,22 +647,27 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, /* * Receive/descriptor errors */ - if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { - if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) + if (!(rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) rs->rs_status |= AR5K_RXERR_CRC; - if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr = AR5K_REG_MS(rxstat1, + rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); if (!ah->ah_capabilities.cap_has_phyerr_counters) ath5k_ani_phy_error_report(ah, rs->rs_phyerr); } - if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) rs->rs_status |= AR5K_RXERR_DECRYPT; - if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) rs->rs_status |= AR5K_RXERR_MIC; } return 0; diff --git a/trunk/drivers/net/wireless/ath/ath5k/eeprom.c b/trunk/drivers/net/wireless/ath/ath5k/eeprom.c index e9263e4c7f3e..b6561f785c6e 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath5k/eeprom.c @@ -660,53 +660,6 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; } -static int -ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *chinfo; - u8 pier, pdg; - - switch (mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - if (!chinfo[pier].pd_curves) - continue; - - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[pdg]; - - if (pd != NULL) { - kfree(pd->pd_step); - kfree(pd->pd_pwr); - } - } - - kfree(chinfo[pier].pd_curves); - } - - return 0; -} - /* Convert RF5111 specific data to generic raw data * used by interpolation code */ static int @@ -731,7 +684,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, GFP_KERNEL); if (!chinfo[pier].pd_curves) - goto err_out; + return -ENOMEM; /* Only one curve for RF5111 * find out which one and place @@ -755,12 +708,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(u8), GFP_KERNEL); if (!pd->pd_step) - goto err_out; + return -ENOMEM; pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - goto err_out; + return -ENOMEM; /* Fill raw dataset * (convert power to 0.25dB units @@ -781,10 +734,6 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, } return 0; - -err_out: - ath5k_eeprom_free_pcal_info(ah, mode); - return -ENOMEM; } /* Parse EEPROM data */ @@ -918,7 +867,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, GFP_KERNEL); if (!chinfo[pier].pd_curves) - goto err_out; + return -ENOMEM; /* Fill pd_curves */ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { @@ -937,13 +886,14 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, sizeof(u8), GFP_KERNEL); if (!pd->pd_step) - goto err_out; + return -ENOMEM; pd->pd_pwr = kcalloc(pd->pd_points, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - goto err_out; + return -ENOMEM; + /* Fill raw dataset * (all power levels are in 0.25dB units) */ @@ -975,13 +925,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, sizeof(u8), GFP_KERNEL); if (!pd->pd_step) - goto err_out; + return -ENOMEM; pd->pd_pwr = kcalloc(pd->pd_points, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - goto err_out; + return -ENOMEM; /* Fill raw dataset * (all power levels are in 0.25dB units) */ @@ -1004,10 +954,6 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, } return 0; - -err_out: - ath5k_eeprom_free_pcal_info(ah, mode); - return -ENOMEM; } /* Parse EEPROM data */ @@ -1210,7 +1156,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, GFP_KERNEL); if (!chinfo[pier].pd_curves) - goto err_out; + return -ENOMEM; /* Fill pd_curves */ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { @@ -1231,13 +1177,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, sizeof(u8), GFP_KERNEL); if (!pd->pd_step) - goto err_out; + return -ENOMEM; pd->pd_pwr = kcalloc(pd->pd_points, sizeof(s16), GFP_KERNEL); if (!pd->pd_pwr) - goto err_out; + return -ENOMEM; /* Fill raw dataset * convert all pwr levels to @@ -1267,10 +1213,6 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, } return 0; - -err_out: - ath5k_eeprom_free_pcal_info(ah, mode); - return -ENOMEM; } /* Parse EEPROM data */ @@ -1592,6 +1534,53 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) return 0; } +static int +ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *chinfo; + u8 pier, pdg; + + switch (mode) { + case AR5K_EEPROM_MODE_11A: + if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_a; + break; + case AR5K_EEPROM_MODE_11B: + if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_b; + break; + case AR5K_EEPROM_MODE_11G: + if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_g; + break; + default: + return -EINVAL; + } + + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + if (!chinfo[pier].pd_curves) + continue; + + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[pdg]; + + if (pd != NULL) { + kfree(pd->pd_step); + kfree(pd->pd_pwr); + } + } + + kfree(chinfo[pier].pd_curves); + } + + return 0; +} + /* Read conformance test limits used for regulatory control */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) @@ -1732,6 +1721,35 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) return ret; } +/* + * Read the MAC address from eeprom + */ +int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ + u8 mac_d[ETH_ALEN] = {}; + u32 total, offset; + u16 data; + int octet; + + AR5K_EEPROM_READ(0x20, data); + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { + AR5K_EEPROM_READ(offset, data); + + total += data; + mac_d[octet + 1] = data & 0xff; + mac_d[octet] = data >> 8; + octet += 2; + } + + if (!total || total == 3 * 0xffff) + return -EINVAL; + + memcpy(mac, mac_d, ETH_ALEN); + + return 0; +} + /***********************\ * Init/Detach functions * diff --git a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 807bd6440169..9be29b728b1c 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -282,15 +282,6 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_BEACON_INT) sc->bintval = bss_conf->beacon_int; - if (changes & BSS_CHANGED_ERP_SLOT) { - int slot_time; - - ah->ah_short_slot = bss_conf->use_short_slot; - slot_time = ath5k_hw_get_default_slottime(ah) + - 3 * ah->ah_coverage_class; - ath5k_hw_set_ifs_intervals(ah, slot_time); - } - if (changes & BSS_CHANGED_ASSOC) { avf->assoc = bss_conf->assoc; if (bss_conf->assoc) diff --git a/trunk/drivers/net/wireless/ath/ath5k/pci.c b/trunk/drivers/net/wireless/ath/ath5k/pci.c index 5cc4a2fe47b6..66598a0d1df0 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath5k/pci.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "../ath.h" #include "ath5k.h" #include "debug.h" @@ -109,42 +108,11 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) return 0; } -/* - * Read the MAC address from eeprom or platform_data - */ -static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) -{ - u8 mac_d[ETH_ALEN] = {}; - u32 total, offset; - u16 data; - int octet; - - AR5K_EEPROM_READ(0x20, data); - - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { - AR5K_EEPROM_READ(offset, data); - - total += data; - mac_d[octet + 1] = data & 0xff; - mac_d[octet] = data >> 8; - octet += 2; - } - - if (!total || total == 3 * 0xffff) - return -EINVAL; - - memcpy(mac, mac_d, ETH_ALEN); - - return 0; -} - - /* Common ath_bus_opts structure */ static const struct ath_bus_ops ath_pci_bus_ops = { .ath_bus_type = ATH_PCI, .read_cachesize = ath5k_pci_read_cachesize, .eeprom_read = ath5k_pci_eeprom_read, - .eeprom_read_mac = ath5k_pci_eeprom_read_mac, }; /********************\ diff --git a/trunk/drivers/net/wireless/ath/ath5k/pcu.c b/trunk/drivers/net/wireless/ath/ath5k/pcu.c index 71b60b7c617e..a702817daf72 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/pcu.c +++ b/trunk/drivers/net/wireless/ath/ath5k/pcu.c @@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] = * bwmodes. */ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, - int len, struct ieee80211_rate *rate, bool shortpre) + int len, struct ieee80211_rate *rate) { struct ath5k_softc *sc = ah->ah_sc; int sifs, preamble, plcp_bits, sym_time; @@ -84,15 +84,9 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, /* Fallback */ if (!ah->ah_bwmode) { - __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, - NULL, len, rate); - - /* subtract difference between long and short preamble */ - dur = le16_to_cpu(raw_dur); - if (shortpre) - dur -= 96; - - return dur; + dur = ieee80211_generic_frame_duration(sc->hw, + NULL, len, rate); + return le16_to_cpu(dur); } bitrate = rate->bitrate; @@ -151,9 +145,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; break; case AR5K_BWMODE_DEFAULT: - default: slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; - if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot) + default: + if (channel->hw_value & CHANNEL_CCK) slot_time = AR5K_INIT_SLOT_TIME_B; break; } @@ -269,14 +263,27 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) * actual rate for this rate. See mac80211 tx.c * ieee80211_duration() for a brief description of * what rate we should choose to TX ACKs. */ - tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); ath5k_hw_reg_write(ah, tx_time, reg); if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) continue; - tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true); + /* + * We're not distinguishing short preamble here, + * This is true, all we'll get is a longer value here + * which is not necessarilly bad. We could use + * export ieee80211_frame_duration() but that needs to be + * fixed first to be properly used by mac802111 drivers: + * + * - remove erp stuff and let the routine figure ofdm + * erp rates + * - remove passing argument ieee80211_local as + * drivers don't have access to it + * - move drivers using ieee80211_generic_frame_duration() + * to this + */ ath5k_hw_reg_write(ah, tx_time, reg + (AR5K_SET_SHORT_PREAMBLE << 2)); } diff --git a/trunk/drivers/net/wireless/ath/ath5k/qcu.c b/trunk/drivers/net/wireless/ath/ath5k/qcu.c index b18c5021aac3..3343fb9e4940 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/qcu.c +++ b/trunk/drivers/net/wireless/ath/ath5k/qcu.c @@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) return -EINVAL; sifs = ath5k_hw_get_default_sifs(ah); - sifs_clock = ath5k_hw_htoclock(ah, sifs - 2); + sifs_clock = ath5k_hw_htoclock(ah, sifs); /* EIFS * Txtime of ack at lowest rate + SIFS + DIFS @@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) else rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; - ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); + ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); /* ack_tx_time includes an SIFS already */ eifs = ack_tx_time + sifs + 2 * slot_time; diff --git a/trunk/drivers/net/wireless/ath/ath5k/reset.c b/trunk/drivers/net/wireless/ath/ath5k/reset.c index 3510de2cf622..84206898f77d 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/reset.c +++ b/trunk/drivers/net/wireless/ath/ath5k/reset.c @@ -158,11 +158,6 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); - /* - * Set default Tx frame to Tx data start delay - */ - txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; - /* * 5210 initvals don't include usec settings * so we need to use magic values here for diff --git a/trunk/drivers/net/wireless/ath/ath9k/Kconfig b/trunk/drivers/net/wireless/ath/ath9k/Kconfig index d9ff8413ab9a..ad57a6d23110 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath9k/Kconfig @@ -5,7 +5,7 @@ config ATH9K_COMMON config ATH9K tristate "Atheros 802.11n wireless cards support" - depends on MAC80211 + depends on PCI && MAC80211 select ATH9K_HW select MAC80211_LEDS select LEDS_CLASS @@ -23,25 +23,6 @@ config ATH9K If you choose to build a module, it'll be called ath9k. -config ATH9K_PCI - bool "Atheros ath9k PCI/PCIe bus support" - depends on ATH9K && PCI - default PCI - ---help--- - This option enables the PCI bus support in ath9k. - - Say Y, if you have a compatible PCI/PCIe wireless card. - -config ATH9K_AHB - bool "Atheros ath9k AHB bus support" - depends on ATH9K - default n - ---help--- - This option enables the AHB bus support in ath9k. - - Say Y, if you have a SoC with a compatible built-in - wireless MAC. Say N if unsure. - config ATH9K_DEBUGFS bool "Atheros ath9k debugging" depends on ATH9K && DEBUG_FS diff --git a/trunk/drivers/net/wireless/ath/ath9k/Makefile b/trunk/drivers/net/wireless/ath/ath9k/Makefile index 05a6fade7b1c..4d66ca8042eb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Makefile +++ b/trunk/drivers/net/wireless/ath/ath9k/Makefile @@ -6,8 +6,8 @@ ath9k-y += beacon.o \ xmit.o \ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o -ath9k-$(CONFIG_ATH9K_PCI) += pci.o -ath9k-$(CONFIG_ATH9K_AHB) += ahb.o +ath9k-$(CONFIG_PCI) += pci.o +ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o @@ -48,6 +48,4 @@ ath9k_htc-y += htc_hst.o \ htc_drv_init.o \ htc_drv_gpio.o -ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o - obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o diff --git a/trunk/drivers/net/wireless/ath/ath9k/ahb.c b/trunk/drivers/net/wireless/ath/ath9k/ahb.c index 61956392f2da..9cb0efa9b4c0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ahb.c @@ -21,18 +21,6 @@ #include #include "ath9k.h" -static const struct platform_device_id ath9k_platform_id_table[] = { - { - .name = "ath9k", - .driver_data = AR5416_AR9100_DEVID, - }, - { - .name = "ar934x_wmac", - .driver_data = AR9300_DEVID_AR9340, - }, - {}, -}; - /* return bus cachesize in 4B word units */ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) { @@ -69,7 +57,6 @@ static int ath_ahb_probe(struct platform_device *pdev) struct ath_softc *sc; struct ieee80211_hw *hw; struct resource *res; - const struct platform_device_id *id = platform_get_device_id(pdev); int irq; int ret = 0; struct ath_hw *ah; @@ -129,7 +116,7 @@ static int ath_ahb_probe(struct platform_device *pdev) goto err_free_hw; } - ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops); + ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); if (ret) { dev_err(&pdev->dev, "failed to initialize device\n"); goto err_irq; @@ -178,11 +165,8 @@ static struct platform_driver ath_ahb_driver = { .name = "ath9k", .owner = THIS_MODULE, }, - .id_table = ath9k_platform_id_table, }; -MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table); - int ath_ahb_init(void) { return platform_driver_register(&ath_ahb_driver); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ani.c b/trunk/drivers/net/wireless/ath/ath9k/ani.c index 5a1f4f511bc1..2e31c775351f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ani.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ani.c @@ -899,6 +899,12 @@ void ath9k_hw_ani_init(struct ath_hw *ah) * check here default level should not modify INI setting. */ if (use_new_ani(ah)) { + const struct ani_ofdm_level_entry *entry_ofdm; + const struct ani_cck_level_entry *entry_cck; + + entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; + entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; + ah->aniperiod = ATH9K_ANI_PERIOD_NEW; ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; } else { diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 4361704fe0d0..ffcf44a4058b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -44,34 +44,6 @@ static const int m1ThreshExt_off = 127; static const int m2ThreshExt_off = 127; -static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array, - int col) -{ - int i; - - for (i = 0; i < array->ia_rows; i++) - bank[i] = INI_RA(array, i, col); -} - - -#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \ - ar5008_write_rf_array(ah, iniarray, regData, &(regWr)) - -static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array, - u32 *data, unsigned int *writecnt) -{ - int r; - - ENABLE_REGWRITE_BUFFER(ah); - - for (r = 0; r < array->ia_rows; r++) { - REG_WRITE(ah, INI_RA(array, r, 0), data[r]); - DO_DELAY(*writecnt); - } - - REGWRITE_BUFFER_FLUSH(ah); -} - /** * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters * @rfbuf: @@ -558,16 +530,16 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); /* Setup Bank 0 Write */ - ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1); + RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); /* Setup Bank 1 Write */ - ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1); + RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); /* Setup Bank 2 Write */ - ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1); + RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); /* Setup Bank 6 Write */ - ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3, + RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, modesIndex); { int i; @@ -597,7 +569,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, } /* Setup Bank 7 Setup */ - ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1); + RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); /* Write Analog registers */ REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, @@ -757,7 +729,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ath_common *common = ath9k_hw_common(ah); int i, regWrites = 0; struct ieee80211_channel *channel = chan->chan; u32 modesIndex, freqIndex; @@ -834,8 +805,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE(ah, reg, val); if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg - && (common->bus_ops->ath_bus_type != ATH_USB)) { + && ah->config.analog_shiftreg) { udelay(100); } @@ -865,8 +835,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REG_WRITE(ah, reg, val); if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg - && (common->bus_ops->ath_bus_type != ATH_USB)) { + && ah->config.analog_shiftreg) { udelay(100); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c index cb611b287b35..76388c6d6692 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -26,27 +26,6 @@ enum ar9002_cal_types { IQ_MISMATCH_CAL = BIT(2), }; -static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ar9002_cal_types cal_type) -{ - bool supported = false; - switch (ah->supp_cals & cal_type) { - case IQ_MISMATCH_CAL: - /* Run IQ Mismatch for non-CCK only */ - if (!IS_CHAN_B(chan)) - supported = true; - break; - case ADC_GAIN_CAL: - case ADC_DC_CAL: - /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ - if (!IS_CHAN_B(chan) && - !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) - supported = true; - break; - } - return supported; -} static void ar9002_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal) @@ -879,32 +858,26 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { ah->supp_cals = IQ_MISMATCH_CAL; - if (AR_SREV_9160_10_OR_LATER(ah)) + if (AR_SREV_9160_10_OR_LATER(ah) && + !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) { ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; - if (AR_SREV_9287(ah)) - ah->supp_cals &= ~ADC_GAIN_CAL; - if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) { INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); - } + "enabling ADC Gain Calibration.\n"); - if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + "enabling ADC DC Calibration.\n"); } - if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) { - INIT_CAL(&ah->iq_caldata); - INSERT_CAL(ah, &ah->iq_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); - } + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + ath_dbg(common, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); ah->cal_list_curr = ah->cal_list; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c index c338efbccf40..399ab3bb299b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -290,6 +290,7 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(txPower, AR_XmitPower) | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); @@ -310,16 +311,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, } } -static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (val) - ads->ds_ctl0 |= AR_ClrDestMask; - else - ads->ds_ctl0 &= ~AR_ClrDestMask; -} - static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, void *lastds, u32 durUpdateEn, u32 rtsctsRate, @@ -424,6 +415,17 @@ static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); } +static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (vmf) + ads->ds_ctl0 |= AR_VirtMoreFrag; + else + ads->ds_ctl0 &= ~AR_VirtMoreFrag; +} + void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, u32 size, u32 flags) { @@ -457,5 +459,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; ops->clr11n_aggr = ar9002_hw_clr11n_aggr; ops->set11n_burstduration = ar9002_hw_set11n_burstduration; - ops->set_clrdmask = ar9002_hw_set_clrdmask; + ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 47780ef1c892..37663dbbcf57 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -483,11 +483,7 @@ #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 -#define AR_PHY_TX_PWRCTRL8 0xa278 - #define AR_PHY_TX_PWRCTRL9 0xa27C - -#define AR_PHY_TX_PWRCTRL10 0xa394 #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 @@ -499,8 +495,6 @@ #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 -#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc -#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index f915a3dbfcad..9ecca93392e8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -34,10 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = { static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, @@ -119,14 +119,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -835,10 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, @@ -920,14 +920,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, @@ -941,10 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, + {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, + {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, @@ -1026,14 +1026,14 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, + {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, + {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, + {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, + {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -1307,10 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, - {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, @@ -1329,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, @@ -1361,45 +1361,45 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, - {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, - {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, - {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, - {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f276cb922b4d..4a4cd88429c0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -18,13 +18,13 @@ #include "hw-ops.h" #include "ar9003_phy.h" +#define MPASS 3 #define MAX_MEASUREMENT 8 -#define MAX_MAG_DELTA 11 -#define MAX_PHS_DELTA 10 +#define MAX_DIFFERENCE 10 struct coeff { - int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; - int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; + int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; + int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; int iqc_coeff[2]; }; @@ -185,19 +185,17 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) /* Accumulate IQ cal measures for active chains */ for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (ah->txchainmask & BIT(i)) { - ah->totalPowerMeasI[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalPowerMeasQ[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalIqCorrMeas[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); - } + ah->totalPowerMeasI[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalPowerMeasQ[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalIqCorrMeas[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); } } @@ -610,48 +608,36 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, return true; } -static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, - int max_delta) +static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) { - int mp_max = -64, max_idx = 0; - int mp_min = 63, min_idx = 0; - int mp_avg = 0, i, outlier_idx = 0; - - /* find min/max mismatch across all calibrated gains */ - for (i = 0; i < nmeasurement; i++) { - mp_avg += mp_coeff[i]; - if (mp_coeff[i] > mp_max) { - mp_max = mp_coeff[i]; - max_idx = i; - } else if (mp_coeff[i] < mp_min) { - mp_min = mp_coeff[i]; - min_idx = i; - } - } + int diff[MPASS]; - /* find average (exclude max abs value) */ - for (i = 0; i < nmeasurement; i++) { - if ((abs(mp_coeff[i]) < abs(mp_max)) || - (abs(mp_coeff[i]) < abs(mp_min))) - mp_avg += mp_coeff[i]; - } - mp_avg /= (nmeasurement - 1); + diff[0] = abs(mp_coeff[0] - mp_coeff[1]); + diff[1] = abs(mp_coeff[1] - mp_coeff[2]); + diff[2] = abs(mp_coeff[2] - mp_coeff[0]); - /* detect outlier */ - if (abs(mp_max - mp_min) > max_delta) { - if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) - outlier_idx = max_idx; - else - outlier_idx = min_idx; - } - mp_coeff[outlier_idx] = mp_avg; + if (diff[0] > MAX_DIFFERENCE && + diff[1] > MAX_DIFFERENCE && + diff[2] > MAX_DIFFERENCE) + return false; + + if (diff[0] <= diff[1] && diff[0] <= diff[2]) + *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; + else if (diff[1] <= diff[2]) + *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; + else + *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; + + return true; } static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, u8 num_chains, struct coeff *coeff) { + struct ath_common *common = ath9k_hw_common(ah); int i, im, nmeasurement; + int magnitude, phase; u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); @@ -671,28 +657,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, /* Load the average of 2 passes */ for (i = 0; i < num_chains; i++) { - nmeasurement = REG_READ_FIELD(ah, - AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_CALIBRATED_GAINS_0); + if (AR_SREV_9485(ah)) + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0_9485, + AR_PHY_CALIBRATED_GAINS_0); + else + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; - /* detect outlier only if nmeasurement > 1 */ - if (nmeasurement > 1) { - /* Detect magnitude outlier */ - ar9003_hw_detect_outlier(coeff->mag_coeff[i], - nmeasurement, MAX_MAG_DELTA); - - /* Detect phase outlier */ - ar9003_hw_detect_outlier(coeff->phs_coeff[i], - nmeasurement, MAX_PHS_DELTA); - } - for (im = 0; im < nmeasurement; im++) { + /* + * Determine which 2 passes are closest and compute avg + * magnitude + */ + if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], + &magnitude)) + goto disable_txiqcal; - coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | - ((coeff->phs_coeff[i][im] & 0x7f) << 7); + /* + * Determine which 2 passes are closest and compute avg + * phase + */ + if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], + &phase)) + goto disable_txiqcal; + + coeff->iqc_coeff[0] = (magnitude & 0x7f) | + ((phase & 0x7f) << 7); if ((im % 2) == 0) REG_RMW_FIELD(ah, tx_corr_coeff[im][i], @@ -712,37 +707,141 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, return; +disable_txiqcal: + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, + AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); + REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, + AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); + + ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); } -static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) +static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); + static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { + AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_TX_IQCAL_STATUS_B1, + AR_PHY_TX_IQCAL_STATUS_B2, + }; + static const u32 chan_info_tab[] = { + AR_PHY_CHAN_INFO_TAB_0, + AR_PHY_CHAN_INFO_TAB_1, + AR_PHY_CHAN_INFO_TAB_2, + }; + struct coeff coeff; + s32 iq_res[6]; + s32 i, j, ip, im, nmeasurement; + u8 nchains = get_streams(common->tx_chainmask); + + for (ip = 0; ip < MPASS; ip++) { + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, + AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, + DELPT); + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, + AR_PHY_TX_IQCAL_START_DO_CAL); + + if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, + AR_PHY_TX_IQCAL_START_DO_CAL, + 0, AH_WAIT_TIMEOUT)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal not complete.\n"); + goto TX_IQ_CAL_FAILED; + } + + nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_CALIBRATED_GAINS_0); + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; + + for (i = 0; i < nchains; i++) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Doing Tx IQ Cal for chain %d.\n", i); + for (im = 0; im < nmeasurement; im++) { + if (REG_READ(ah, txiqcal_status[i]) & + AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal failed for chain %d.\n", i); + goto TX_IQ_CAL_FAILED; + } + + for (j = 0; j < 3; j++) { + u8 idx = 2 * j, + offset = 4 * (3 * im + j); + + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 0); + + /* 32 bits */ + iq_res[idx] = REG_READ(ah, + chan_info_tab[i] + + offset); + + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 1); + + /* 16 bits */ + iq_res[idx+1] = 0xffff & REG_READ(ah, + chan_info_tab[i] + + offset); + + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", + idx, iq_res[idx], idx+1, iq_res[idx+1]); + } + + if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, + coeff.iqc_coeff)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Failed in calculation of IQ correction.\n"); + goto TX_IQ_CAL_FAILED; + } + coeff.mag_coeff[i][im][ip] = + coeff.iqc_coeff[0] & 0x7f; + coeff.phs_coeff[i][im][ip] = + (coeff.iqc_coeff[0] >> 7) & 0x7f; + + if (coeff.mag_coeff[i][im][ip] > 63) + coeff.mag_coeff[i][im][ip] -= 128; + if (coeff.phs_coeff[i][im][ip] > 63) + coeff.phs_coeff[i][im][ip] -= 128; + + } + } + } + + ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); + + return; + +TX_IQ_CAL_FAILED: + ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); +} + +static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) +{ u8 tx_gain_forced; + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, + AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE); if (tx_gain_forced) REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE, 0); - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, - AR_PHY_TX_IQCAL_START_DO_CAL, 1); - - if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, - AR_PHY_TX_IQCAL_START_DO_CAL, 0, - AH_WAIT_TIMEOUT)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal is not completed.\n"); - return false; - } - return true; + REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, + AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); } static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); const u32 txiqcal_status[AR9300_MAX_CHAINS] = { - AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; @@ -754,7 +853,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) struct coeff coeff; s32 iq_res[6]; u8 num_chains = 0; - int i, im, j; + int i, ip, im, j; int nmeasurement; for (i = 0; i < AR9300_MAX_CHAINS; i++) { @@ -762,69 +861,71 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) num_chains++; } - for (i = 0; i < num_chains; i++) { - nmeasurement = REG_READ_FIELD(ah, - AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_CALIBRATED_GAINS_0); - if (nmeasurement > MAX_MEASUREMENT) - nmeasurement = MAX_MEASUREMENT; - - for (im = 0; im < nmeasurement; im++) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Doing Tx IQ Cal for chain %d.\n", i); + for (ip = 0; ip < MPASS; ip++) { + for (i = 0; i < num_chains; i++) { + nmeasurement = REG_READ_FIELD(ah, + AR_PHY_TX_IQCAL_STATUS_B0_9485, + AR_PHY_CALIBRATED_GAINS_0); + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; - if (REG_READ(ah, txiqcal_status[i]) & - AR_PHY_TX_IQCAL_STATUS_FAILED) { + for (im = 0; im < nmeasurement; im++) { ath_dbg(common, ATH_DBG_CALIBRATE, + "Doing Tx IQ Cal for chain %d.\n", i); + + if (REG_READ(ah, txiqcal_status[i]) & + AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed for chain %d.\n", i); - goto tx_iqcal_fail; - } + goto tx_iqcal_fail; + } - for (j = 0; j < 3; j++) { - u32 idx = 2 * j, offset = 4 * (3 * im + j); + for (j = 0; j < 3; j++) { + u32 idx = 2 * j, offset = 4 * (3 * im + j); - REG_RMW_FIELD(ah, + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 0); - /* 32 bits */ - iq_res[idx] = REG_READ(ah, - chan_info_tab[i] + - offset); + /* 32 bits */ + iq_res[idx] = REG_READ(ah, + chan_info_tab[i] + + offset); - REG_RMW_FIELD(ah, + REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 1); - /* 16 bits */ - iq_res[idx + 1] = 0xffff & REG_READ(ah, - chan_info_tab[i] + offset); + /* 16 bits */ + iq_res[idx + 1] = 0xffff & REG_READ(ah, + chan_info_tab[i] + offset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "IQ RES[%d]=0x%x" - "IQ_RES[%d]=0x%x\n", - idx, iq_res[idx], idx + 1, - iq_res[idx + 1]); - } + ath_dbg(common, ATH_DBG_CALIBRATE, + "IQ RES[%d]=0x%x" + "IQ_RES[%d]=0x%x\n", + idx, iq_res[idx], idx + 1, + iq_res[idx + 1]); + } - if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, - coeff.iqc_coeff)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "Failed in calculation of \ - IQ correction.\n"); - goto tx_iqcal_fail; - } + if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, + coeff.iqc_coeff)) { + ath_dbg(common, ATH_DBG_CALIBRATE, + "Failed in calculation of IQ correction.\n"); + goto tx_iqcal_fail; + } - coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; - coeff.phs_coeff[i][im] = - (coeff.iqc_coeff[0] >> 7) & 0x7f; + coeff.mag_coeff[i][im][ip] = + coeff.iqc_coeff[0] & 0x7f; + coeff.phs_coeff[i][im][ip] = + (coeff.iqc_coeff[0] >> 7) & 0x7f; - if (coeff.mag_coeff[i][im] > 63) - coeff.mag_coeff[i][im] -= 128; - if (coeff.phs_coeff[i][im] > 63) - coeff.phs_coeff[i][im] -= 128; + if (coeff.mag_coeff[i][im][ip] > 63) + coeff.mag_coeff[i][im][ip] -= 128; + if (coeff.phs_coeff[i][im][ip] > 63) + coeff.phs_coeff[i][im][ip] -= 128; + } } } ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); @@ -839,37 +940,31 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_capabilities *pCap = &ah->caps; int val; - bool txiqcal_done = false; val = REG_READ(ah, AR_ENT_OTP); ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); - /* Configure rx/tx chains before running AGC/TxiQ cals */ - if (val & AR_ENT_OTP_CHAIN2_DISABLE) + if (AR_SREV_9485(ah)) + ar9003_hw_set_chain_masks(ah, 0x1, 0x1); + else if (val & AR_ENT_OTP_CHAIN2_DISABLE) ar9003_hw_set_chain_masks(ah, 0x3, 0x3); else - ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, - pCap->tx_chainmask); + /* + * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain + * mode before running AGC/TxIQ cals + */ + ar9003_hw_set_chain_masks(ah, 0x7, 0x7); /* Do Tx IQ Calibration */ - REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, - AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, - DELPT); + if (AR_SREV_9485(ah)) + ar9003_hw_tx_iq_cal_run(ah); + else + ar9003_hw_tx_iq_cal(ah); - /* - * For AR9485 or later chips, TxIQ cal runs as part of - * AGC calibration - */ - if (AR_SREV_9485_OR_LATER(ah)) - txiqcal_done = true; - else { - txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); - udelay(5); - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - } + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); + udelay(5); + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, @@ -884,7 +979,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, return false; } - if (txiqcal_done) + if (AR_SREV_9485(ah)) ar9003_hw_tx_iq_cal_post_proc(ah); /* Revert chainmasks to their original values before NF cal */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 97f970c5e4ec..4a9271802991 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3217,6 +3217,7 @@ static int ar9300_compress_decision(struct ath_hw *ah, u8 *word, int length, int mdata_size) { struct ath_common *common = ath9k_hw_common(ah); + u8 *dptr; const struct ar9300_eeprom *eep = NULL; switch (code) { @@ -3234,6 +3235,7 @@ static int ar9300_compress_decision(struct ath_hw *ah, break; case _CompressBlock: if (reference == 0) { + dptr = mptr; } else { eep = ar9003_eeprom_struct_find_by_id(reference); if (eep == NULL) { @@ -3446,13 +3448,9 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); else { REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); - if (!AR_SREV_9340(ah)) { - REG_RMW_FIELD(ah, AR_CH0_THERM, - AR_CH0_THERM_XPABIASLVL_MSB, - bias >> 2); - REG_RMW_FIELD(ah, AR_CH0_THERM, - AR_CH0_THERM_XPASHORT2GND, 1); - } + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, + bias >> 2); + REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); } } @@ -3499,28 +3497,23 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { - int chain; - static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { - AR_PHY_SWITCH_CHAIN_0, - AR_PHY_SWITCH_CHAIN_1, - AR_PHY_SWITCH_CHAIN_2, - }; - u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); - for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if ((ah->rxchainmask & BIT(chain)) || - (ah->txchainmask & BIT(chain))) { - value = ar9003_hw_ant_ctrl_chain_get(ah, chain, - is2ghz); - REG_RMW_FIELD(ah, switch_chain_reg[chain], - AR_SWITCH_TABLE_ALL, value); - } + value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); + + if (!AR_SREV_9485(ah)) { + value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, + value); + + value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); + REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, + value); } if (AR_SREV_9485(ah)) { @@ -3641,16 +3634,13 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) /* Test value. if 0 then attenuation is unused. Don't load anything. */ for (i = 0; i < 3; i++) { - if (ah->txchainmask & BIT(i)) { - value = ar9003_hw_atten_chain_get(ah, i, chan); - REG_RMW_FIELD(ah, ext_atten_reg[i], - AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); - - value = ar9003_hw_atten_chain_get_margin(ah, i, chan); - REG_RMW_FIELD(ah, ext_atten_reg[i], - AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, - value); - } + value = ar9003_hw_atten_chain_get(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); + + value = ar9003_hw_atten_chain_get_margin(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], + AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); } } @@ -3759,9 +3749,8 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_drive_strength_apply(ah); ar9003_hw_atten_apply(ah, chan); - if (!AR_SREV_9340(ah)) - ar9003_hw_internal_regulator_apply(ah); - if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) + ar9003_hw_internal_regulator_apply(ah); + if (AR_SREV_9485(ah)) ar9003_hw_apply_tuning_caps(ah); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c index a55eddbb2589..7f5de6e4448b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -18,7 +18,6 @@ #include "ar9003_mac.h" #include "ar9003_2p2_initvals.h" #include "ar9485_initvals.h" -#include "ar9340_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -29,105 +28,109 @@ */ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) { - if (AR_SREV_9340(ah)) { + if (AR_SREV_9485_11(ah)) { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9340_1p0_mac_core, - ARRAY_SIZE(ar9340_1p0_mac_core), 2); + ar9485_1_1_mac_core, + ARRAY_SIZE(ar9485_1_1_mac_core), 2); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9340_1p0_mac_postamble, - ARRAY_SIZE(ar9340_1p0_mac_postamble), 5); + ar9485_1_1_mac_postamble, + ARRAY_SIZE(ar9485_1_1_mac_postamble), 5); /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1, + ARRAY_SIZE(ar9485_1_1), 2); INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9340_1p0_baseband_core, - ARRAY_SIZE(ar9340_1p0_baseband_core), 2); + ar9485_1_1_baseband_core, + ARRAY_SIZE(ar9485_1_1_baseband_core), 2); INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9340_1p0_baseband_postamble, - ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5); + ar9485_1_1_baseband_postamble, + ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9340_1p0_radio_core, - ARRAY_SIZE(ar9340_1p0_radio_core), 2); + ar9485_1_1_radio_core, + ARRAY_SIZE(ar9485_1_1_radio_core), 2); INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9340_1p0_radio_postamble, - ARRAY_SIZE(ar9340_1p0_radio_postamble), 5); + ar9485_1_1_radio_postamble, + ARRAY_SIZE(ar9485_1_1_radio_postamble), 2); /* soc */ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9340_1p0_soc_preamble, - ARRAY_SIZE(ar9340_1p0_soc_preamble), 2); + ar9485_1_1_soc_preamble, + ARRAY_SIZE(ar9485_1_1_soc_preamble), 2); INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], - ar9340_1p0_soc_postamble, - ARRAY_SIZE(ar9340_1p0_soc_postamble), 5); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); /* rx/tx gain */ INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9340Common_wo_xlna_rx_gain_table_1p0, - ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), - 5); + ar9485_common_rx_gain_1_1, + ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2); INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9340Modes_high_ob_db_tx_gain_table_1p0, - ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0), + ar9485_modes_lowest_ob_db_tx_gain_1_1, + ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 5); - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9340Modes_fast_clock_1p0, - ARRAY_SIZE(ar9340Modes_fast_clock_1p0), - 3); + /* Load PCIE SERDES settings from INI */ + + /* Awake Setting */ + + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9485_1_1_pcie_phy_clkreq_disable_L1, + ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), + 2); + + /* Sleep Setting */ - INIT_INI_ARRAY(&ah->iniModesAdditional_40M, - ar9340_1p0_radio_core_40M, - ARRAY_SIZE(ar9340_1p0_radio_core_40M), + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, + ar9485_1_1_pcie_phy_clkreq_disable_L1, + ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), 2); - } else if (AR_SREV_9485_11(ah)) { + } else if (AR_SREV_9485(ah)) { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9485_1_1_mac_core, - ARRAY_SIZE(ar9485_1_1_mac_core), 2); + ar9485_1_0_mac_core, + ARRAY_SIZE(ar9485_1_0_mac_core), 2); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9485_1_1_mac_postamble, - ARRAY_SIZE(ar9485_1_1_mac_postamble), 5); + ar9485_1_0_mac_postamble, + ARRAY_SIZE(ar9485_1_0_mac_postamble), 5); /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1, - ARRAY_SIZE(ar9485_1_1), 2); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0, + ARRAY_SIZE(ar9485_1_0), 2); INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9485_1_1_baseband_core, - ARRAY_SIZE(ar9485_1_1_baseband_core), 2); + ar9485_1_0_baseband_core, + ARRAY_SIZE(ar9485_1_0_baseband_core), 2); INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9485_1_1_baseband_postamble, - ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5); + ar9485_1_0_baseband_postamble, + ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5); /* radio */ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9485_1_1_radio_core, - ARRAY_SIZE(ar9485_1_1_radio_core), 2); + ar9485_1_0_radio_core, + ARRAY_SIZE(ar9485_1_0_radio_core), 2); INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9485_1_1_radio_postamble, - ARRAY_SIZE(ar9485_1_1_radio_postamble), 2); + ar9485_1_0_radio_postamble, + ARRAY_SIZE(ar9485_1_0_radio_postamble), 2); /* soc */ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9485_1_1_soc_preamble, - ARRAY_SIZE(ar9485_1_1_soc_preamble), 2); + ar9485_1_0_soc_preamble, + ARRAY_SIZE(ar9485_1_0_soc_preamble), 2); INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); /* rx/tx gain */ INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485Common_wo_xlna_rx_gain_1_1, - ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); + ar9485Common_rx_gain_1_0, + ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2); INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9485_modes_lowest_ob_db_tx_gain_1_1, - ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), + ar9485Modes_lowest_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), 5); /* Load PCIE SERDES settings from INI */ @@ -135,15 +138,15 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) /* Awake Setting */ INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9485_1_1_pcie_phy_clkreq_disable_L1, - ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), + ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, + ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), 2); /* Sleep Setting */ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9485_1_1_pcie_phy_clkreq_disable_L1, - ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), + ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, + ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), 2); } else { /* mac */ @@ -220,16 +223,16 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_tx_gain_idx(ah)) { case 0: default: - if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9340Modes_lowest_ob_db_tx_gain_table_1p0, - ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); - else if (AR_SREV_9485_11(ah)) + if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485_modes_lowest_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), 5); + else if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_lowest_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_lowest_ob_db_tx_gain_table_2p2, @@ -237,16 +240,16 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 5); break; case 1: - if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9340Modes_lowest_ob_db_tx_gain_table_1p0, - ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); - else if (AR_SREV_9485_11(ah)) + if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_high_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), 5); + else if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_high_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_0), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_ob_db_tx_gain_table_2p2, @@ -254,16 +257,16 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 5); break; case 2: - if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9340Modes_lowest_ob_db_tx_gain_table_1p0, - ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); - else if (AR_SREV_9485_11(ah)) + if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_low_ob_db_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), 5); + else if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_low_ob_db_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_0), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_low_ob_db_tx_gain_table_2p2, @@ -271,16 +274,16 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 5); break; case 3: - if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9340Modes_lowest_ob_db_tx_gain_table_1p0, - ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); - else if (AR_SREV_9485_11(ah)) + if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_high_power_tx_gain_1_1, ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), 5); + else if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9485Modes_high_power_tx_gain_1_0, + ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0), + 5); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_high_power_tx_gain_table_2p2, @@ -295,15 +298,15 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_rx_gain_idx(ah)) { case 0: default: - if (AR_SREV_9340(ah)) + if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9340Common_rx_gain_table_1p0, - ARRAY_SIZE(ar9340Common_rx_gain_table_1p0), + ar9485_common_rx_gain_1_1, + ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2); - else if (AR_SREV_9485_11(ah)) + else if (AR_SREV_9485(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485Common_wo_xlna_rx_gain_1_1, - ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), + ar9485Common_rx_gain_1_0, + ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, @@ -312,16 +315,16 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) 2); break; case 1: - if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9340Common_wo_xlna_rx_gain_table_1p0, - ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), - 2); - else if (AR_SREV_9485_11(ah)) + if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9485Common_wo_xlna_rx_gain_1_1, ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); + else if (AR_SREV_9485(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9485Common_wo_xlna_rx_gain_1_0, + ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0), + 2); else INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_wo_xlna_rx_gain_table_2p2, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c index c1264d60c499..038a0cbfc6e7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -329,6 +329,7 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(txpower, AR_XmitPower) | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); @@ -349,16 +350,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, ads->ctl22 = 0; } -static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) -{ - struct ar9003_txc *ads = (struct ar9003_txc *) ds; - - if (val) - ads->ctl11 |= AR_ClrDestMask; - else - ads->ctl11 &= ~AR_ClrDestMask; -} - static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, void *lastds, u32 durUpdateEn, u32 rtsctsRate, @@ -494,6 +485,17 @@ static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, } +static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) +{ + struct ar9003_txc *ads = (struct ar9003_txc *) ds; + + if (vmf) + ads->ctl11 |= AR_VirtMoreFrag; + else + ads->ctl11 &= ~AR_VirtMoreFrag; +} + void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) { struct ar9003_txc *ads = ds; @@ -519,7 +521,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; ops->clr11n_aggr = ar9003_hw_clr11n_aggr; ops->set11n_burstduration = ar9003_hw_set11n_burstduration; - ops->set_clrdmask = ar9003_hw_set_clrdmask; + ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; } void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c83be2dd5718..eb250d6b8038 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -75,42 +75,16 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) freq = centers.synth_center; if (freq < 4800) { /* 2 GHz, fractional mode */ - if (AR_SREV_9485(ah)) { - u32 chan_frac; - - /* - * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0 - * ndiv = ((chan_mhz * 4) / 3) / freq_ref; - * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 - */ - channelSel = (freq * 4) / 120; - chan_frac = (((freq * 4) % 120) * 0x20000) / 120; - channelSel = (channelSel << 17) | chan_frac; - } else if (AR_SREV_9340(ah)) { - if (ah->is_clk_25mhz) { - u32 chan_frac; - - channelSel = (freq * 2) / 75; - chan_frac = (((freq * 2) % 75) * 0x20000) / 75; - channelSel = (channelSel << 17) | chan_frac; - } else - channelSel = CHANSEL_2G(freq) >> 1; - } else + if (AR_SREV_9485(ah)) + channelSel = CHANSEL_2G_9485(freq); + else channelSel = CHANSEL_2G(freq); /* Set to 2G mode */ bMode = 1; } else { - if (AR_SREV_9340(ah) && ah->is_clk_25mhz) { - u32 chan_frac; - - channelSel = (freq * 2) / 75; - chan_frac = ((freq % 75) * 0x20000) / 75; - channelSel = (channelSel << 17) | chan_frac; - } else { - channelSel = CHANSEL_5G(freq); - /* Doubler is ON, so, divide channelSel by 2. */ - channelSel >>= 1; - } + channelSel = CHANSEL_5G(freq); + /* Doubler is ON, so, divide channelSel by 2. */ + channelSel >>= 1; /* Set to 5G mode */ bMode = 0; } @@ -168,7 +142,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, * is out-of-band and can be ignored. */ - if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) { + if (AR_SREV_9485(ah)) { spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan)); if (spur_fbin_ptr[0] == 0) /* No spur */ @@ -193,7 +167,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, for (i = 0; i < max_spur_cnts; i++) { negative = 0; - if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) + if (AR_SREV_9485(ah)) cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], IS_CHAN_2GHZ(chan)) - synth_freq; else @@ -427,7 +401,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, ar9003_hw_spur_ofdm_clear(ah); - for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { + for (i = 0; spurChansPtr[i] && i < 5; i++) { freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; if (abs(freq_offset) < range) { ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); @@ -616,25 +590,29 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); unsigned int regWrites = 0, i; struct ieee80211_channel *channel = chan->chan; - u32 modesIndex; + u32 modesIndex, freqIndex; switch (chan->chanmode) { case CHANNEL_A: case CHANNEL_A_HT20: modesIndex = 1; + freqIndex = 1; break; case CHANNEL_A_HT40PLUS: case CHANNEL_A_HT40MINUS: modesIndex = 2; + freqIndex = 1; break; case CHANNEL_G: case CHANNEL_G_HT20: case CHANNEL_B: modesIndex = 4; + freqIndex = 2; break; case CHANNEL_G_HT40PLUS: case CHANNEL_G_HT40MINUS: modesIndex = 3; + freqIndex = 2; break; default: @@ -659,9 +637,6 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites); - if (AR_SREV_9340(ah) && !ah->is_clk_25mhz) - REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites); - ar9003_hw_override_ini(ah); ar9003_hw_set_channel_regs(ah, chan); ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 2a0d5cbb7e76..8bdda2cf9dd7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -548,12 +548,15 @@ #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) -#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3c8 : 0x448) -#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3c4 : 0x440) -#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3f0 : 0x48c) +#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4) +#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000 +#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31 +#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8) +#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0) + +#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) +#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) +#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ (AR_SREV_9485(ah) ? \ 0x3d0 : 0x450) + ((_i) << 2)) @@ -585,7 +588,7 @@ #define AR_PHY_65NM_CH0_BIAS2 0x160c4 #define AR_PHY_65NM_CH0_BIAS4 0x160cc #define AR_PHY_65NM_CH0_RXTX4 0x1610c -#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c) +#define AR_PHY_65NM_CH0_THERM (AR_SREV_9485(ah) ? 0x1628c : 0x16290) #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 @@ -755,10 +758,10 @@ #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 -#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 -#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 -#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 -#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 +#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 +#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 +#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 +#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 #define AR_PHY_CALIBRATED_GAINS_0 0x3e diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9340_initvals.h deleted file mode 100644 index 815a8af1beef..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ /dev/null @@ -1,1525 +0,0 @@ -/* - * Copyright (c) 2011 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef INITVALS_9340_H -#define INITVALS_9340_H - -static const u32 ar9340_1p0_radio_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, - {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, - {0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, - {0x0001650c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, - {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, -}; - -static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, - {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, - {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, - {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -}; - -static const u32 ar9340Modes_fast_clock_1p0[][3] = { - /* Addr 5G_HT20 5G_HT40 */ - {0x00001030, 0x00000268, 0x000004d0}, - {0x00001070, 0x0000018c, 0x00000318}, - {0x000010b0, 0x00000fd0, 0x00001fa0}, - {0x00008014, 0x044c044c, 0x08980898}, - {0x0000801c, 0x148ec02b, 0x148ec057}, - {0x00008318, 0x000044c0, 0x00008980}, - {0x00009e00, 0x03721821, 0x03721821}, - {0x0000a230, 0x0000000b, 0x00000016}, - {0x0000a254, 0x00000898, 0x00001130}, -}; - -static const u32 ar9340_1p0_radio_core[][2] = { - /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73f00000}, - {0x0001600c, 0x00000000}, - {0x00016040, 0x7f80fff8}, - {0x00016044, 0x03b6d2db}, - {0x00016048, 0x24925266}, - {0x0001604c, 0x000f0278}, - {0x00016050, 0x6db6db6c}, - {0x00016054, 0x6db60000}, - {0x00016080, 0x00080000}, - {0x00016084, 0x0e48048c}, - {0x00016088, 0x14214514}, - {0x0001608c, 0x119f081c}, - {0x00016090, 0x24926490}, - {0x00016094, 0x00000000}, - {0x00016098, 0xd411eb84}, - {0x0001609c, 0x03e47f32}, - {0x000160a0, 0xc2108ffe}, - {0x000160a4, 0x812fc370}, - {0x000160a8, 0x423c8000}, - {0x000160ac, 0xa4646800}, - {0x000160b0, 0x00fe7f46}, - {0x000160b4, 0x92480000}, - {0x000160c0, 0x006db6db}, - {0x000160c4, 0x6db6db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x6de6db6c}, - {0x000160d0, 0xb6da4924}, - {0x00016100, 0x04cb0001}, - {0x00016104, 0xfff80000}, - {0x00016108, 0x00080010}, - {0x0001610c, 0x00000000}, - {0x00016140, 0x50804008}, - {0x00016144, 0x01884080}, - {0x00016148, 0x000080c0}, - {0x00016280, 0x01000015}, - {0x00016284, 0x05530000}, - {0x00016288, 0x00318000}, - {0x0001628c, 0x50000000}, - {0x00016290, 0x4080294f}, - {0x00016380, 0x00000000}, - {0x00016384, 0x00000000}, - {0x00016388, 0x00800700}, - {0x0001638c, 0x00800700}, - {0x00016390, 0x00800700}, - {0x00016394, 0x00000000}, - {0x00016398, 0x00000000}, - {0x0001639c, 0x00000000}, - {0x000163a0, 0x00000001}, - {0x000163a4, 0x00000001}, - {0x000163a8, 0x00000000}, - {0x000163ac, 0x00000000}, - {0x000163b0, 0x00000000}, - {0x000163b4, 0x00000000}, - {0x000163b8, 0x00000000}, - {0x000163bc, 0x00000000}, - {0x000163c0, 0x000000a0}, - {0x000163c4, 0x000c0000}, - {0x000163c8, 0x14021402}, - {0x000163cc, 0x00001402}, - {0x000163d0, 0x00000000}, - {0x000163d4, 0x00000000}, - {0x00016400, 0x36db6db6}, - {0x00016404, 0x6db6db40}, - {0x00016408, 0x73f00000}, - {0x0001640c, 0x00000000}, - {0x00016440, 0x7f80fff8}, - {0x00016444, 0x03b6d2db}, - {0x00016448, 0x24927266}, - {0x0001644c, 0x000f0278}, - {0x00016450, 0x6db6db6c}, - {0x00016454, 0x6db60000}, - {0x00016500, 0x04cb0001}, - {0x00016504, 0xfff80000}, - {0x00016508, 0x00080010}, - {0x0001650c, 0x00000000}, - {0x00016540, 0x50804008}, - {0x00016544, 0x01884080}, - {0x00016548, 0x000080c0}, - {0x00016780, 0x00000000}, - {0x00016784, 0x00000000}, - {0x00016788, 0x00800700}, - {0x0001678c, 0x00800700}, - {0x00016790, 0x00800700}, - {0x00016794, 0x00000000}, - {0x00016798, 0x00000000}, - {0x0001679c, 0x00000000}, - {0x000167a0, 0x00000001}, - {0x000167a4, 0x00000001}, - {0x000167a8, 0x00000000}, - {0x000167ac, 0x00000000}, - {0x000167b0, 0x00000000}, - {0x000167b4, 0x00000000}, - {0x000167b8, 0x00000000}, - {0x000167bc, 0x00000000}, - {0x000167c0, 0x000000a0}, - {0x000167c4, 0x000c0000}, - {0x000167c8, 0x14021402}, - {0x000167cc, 0x00001402}, - {0x000167d0, 0x00000000}, - {0x000167d4, 0x00000000}, -}; - -static const u32 ar9340_1p0_radio_core_40M[][2] = { - {0x0001609c, 0x02566f3a}, - {0x000160ac, 0xa4647c00}, - {0x000160b0, 0x01885f5a}, -}; - -static const u32 ar9340_1p0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - -static const u32 ar9340_1p0_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, -}; - -static const u32 ar9340_1p0_baseband_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, - {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, - {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, - {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, - {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, - {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e}, - {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, - {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, - {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, - {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, - {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, - {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, - {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, - {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, - {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110}, - {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, - {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, - {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae04, 0x00180000, 0x00180000, 0x00180000, 0x00180000}, - {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, -}; - -static const u32 ar9340_1p0_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, - {0x00009804, 0xfd14e000}, - {0x00009808, 0x9c0a9f6b}, - {0x0000980c, 0x04900000}, - {0x00009814, 0xb280c00a}, - {0x00009818, 0x00000000}, - {0x0000981c, 0x00020028}, - {0x00009834, 0x5f3ca3de}, - {0x00009838, 0x0108ecff}, - {0x0000983c, 0x14750600}, - {0x00009880, 0x201fff00}, - {0x00009884, 0x00001042}, - {0x000098a4, 0x00200400}, - {0x000098b0, 0x52440bbe}, - {0x000098d0, 0x004b6a8e}, - {0x000098d4, 0x00000820}, - {0x000098dc, 0x00000000}, - {0x000098f0, 0x00000000}, - {0x000098f4, 0x00000000}, - {0x00009c04, 0xff55ff55}, - {0x00009c08, 0x0320ff55}, - {0x00009c0c, 0x00000000}, - {0x00009c10, 0x00000000}, - {0x00009c14, 0x00046384}, - {0x00009c18, 0x05b6b440}, - {0x00009c1c, 0x00b6b440}, - {0x00009d00, 0xc080a333}, - {0x00009d04, 0x40206c10}, - {0x00009d08, 0x009c4060}, - {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, - {0x00009d14, 0x00c0040b}, - {0x00009d18, 0x00000000}, - {0x00009e08, 0x0038230c}, - {0x00009e24, 0x990bb515}, - {0x00009e28, 0x0c6f0000}, - {0x00009e30, 0x06336f77}, - {0x00009e34, 0x6af6532f}, - {0x00009e38, 0x0cc80c00}, - {0x00009e3c, 0xcf946222}, - {0x00009e40, 0x0d261820}, - {0x00009e4c, 0x00001004}, - {0x00009e50, 0x00ff03f1}, - {0x00009e54, 0x00000000}, - {0x00009fc0, 0x803e4788}, - {0x00009fc4, 0x0001efb5}, - {0x00009fcc, 0x40000014}, - {0x00009fd0, 0x01193b93}, - {0x0000a20c, 0x00000000}, - {0x0000a220, 0x00000000}, - {0x0000a224, 0x00000000}, - {0x0000a228, 0x10002310}, - {0x0000a22c, 0x01036a1e}, - {0x0000a234, 0x10000fff}, - {0x0000a23c, 0x00000000}, - {0x0000a244, 0x0c000000}, - {0x0000a2a0, 0x00000001}, - {0x0000a2c0, 0x00000001}, - {0x0000a2c8, 0x00000000}, - {0x0000a2cc, 0x18c43433}, - {0x0000a2d4, 0x00000000}, - {0x0000a2dc, 0x00000000}, - {0x0000a2e0, 0x00000000}, - {0x0000a2e4, 0x00000000}, - {0x0000a2e8, 0x00000000}, - {0x0000a2ec, 0x00000000}, - {0x0000a2f0, 0x00000000}, - {0x0000a2f4, 0x00000000}, - {0x0000a2f8, 0x00000000}, - {0x0000a344, 0x00000000}, - {0x0000a34c, 0x00000000}, - {0x0000a350, 0x0000a000}, - {0x0000a364, 0x00000000}, - {0x0000a370, 0x00000000}, - {0x0000a390, 0x00000001}, - {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, - {0x0000a3c0, 0x20202020}, - {0x0000a3c4, 0x22222220}, - {0x0000a3c8, 0x20200020}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3d8, 0x20202020}, - {0x0000a3dc, 0x20202020}, - {0x0000a3e0, 0x20202020}, - {0x0000a3e4, 0x20202020}, - {0x0000a3e8, 0x20202020}, - {0x0000a3ec, 0x20202020}, - {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000246}, - {0x0000a3f8, 0x0cdbd380}, - {0x0000a3fc, 0x000f0f01}, - {0x0000a400, 0x8fa91f01}, - {0x0000a404, 0x00000000}, - {0x0000a408, 0x0e79e5c6}, - {0x0000a40c, 0x00820820}, - {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x2d001dce}, - {0x0000a41c, 0x1ce739ce}, - {0x0000a420, 0x000001ce}, - {0x0000a424, 0x1ce739ce}, - {0x0000a428, 0x000001ce}, - {0x0000a42c, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce}, - {0x0000a434, 0x00000000}, - {0x0000a438, 0x00001801}, - {0x0000a43c, 0x00000000}, - {0x0000a440, 0x00000000}, - {0x0000a444, 0x00000000}, - {0x0000a448, 0x04000080}, - {0x0000a44c, 0x00000001}, - {0x0000a450, 0x00010000}, - {0x0000a458, 0x00000000}, - {0x0000a600, 0x00000000}, - {0x0000a604, 0x00000000}, - {0x0000a608, 0x00000000}, - {0x0000a60c, 0x00000000}, - {0x0000a610, 0x00000000}, - {0x0000a614, 0x00000000}, - {0x0000a618, 0x00000000}, - {0x0000a61c, 0x00000000}, - {0x0000a620, 0x00000000}, - {0x0000a624, 0x00000000}, - {0x0000a628, 0x00000000}, - {0x0000a62c, 0x00000000}, - {0x0000a630, 0x00000000}, - {0x0000a634, 0x00000000}, - {0x0000a638, 0x00000000}, - {0x0000a63c, 0x00000000}, - {0x0000a640, 0x00000000}, - {0x0000a644, 0x3fad9d74}, - {0x0000a648, 0x0048060a}, - {0x0000a64c, 0x00000637}, - {0x0000a670, 0x03020100}, - {0x0000a674, 0x09080504}, - {0x0000a678, 0x0d0c0b0a}, - {0x0000a67c, 0x13121110}, - {0x0000a680, 0x31301514}, - {0x0000a684, 0x35343332}, - {0x0000a688, 0x00000036}, - {0x0000a690, 0x00000838}, - {0x0000a7c0, 0x00000000}, - {0x0000a7c4, 0xfffffffc}, - {0x0000a7c8, 0x00000000}, - {0x0000a7cc, 0x00000000}, - {0x0000a7d0, 0x00000000}, - {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000000}, - {0x0000a8d0, 0x004b6a8e}, - {0x0000a8d4, 0x00000820}, - {0x0000a8dc, 0x00000000}, - {0x0000a8f0, 0x00000000}, - {0x0000a8f4, 0x00000000}, - {0x0000b2d0, 0x00000080}, - {0x0000b2d4, 0x00000000}, - {0x0000b2dc, 0x00000000}, - {0x0000b2e0, 0x00000000}, - {0x0000b2e4, 0x00000000}, - {0x0000b2e8, 0x00000000}, - {0x0000b2ec, 0x00000000}, - {0x0000b2f0, 0x00000000}, - {0x0000b2f4, 0x00000000}, - {0x0000b2f8, 0x00000000}, - {0x0000b408, 0x0e79e5c0}, - {0x0000b40c, 0x00820820}, - {0x0000b420, 0x00000000}, -}; - -static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, - {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, - {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, - {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -}; - -static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, - {0x00016048, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, - {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, - {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, -}; -static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x00016044, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, - {0x00016048, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, - {0x00016444, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, - {0x00016448, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, -}; - - -static const u32 ar9340Common_rx_gain_table_1p0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, - {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, - {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, - {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -}; - -static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x15000402, 0x15000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, - {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, - {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, - {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, - {0x00016048, 0x24927266, 0x24927266, 0x8e483266, 0x8e483266}, - {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, - {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266}, -}; - -static const u32 ar9340_1p0_mac_core[][2] = { - /* Addr allmodes */ - {0x00000008, 0x00000000}, - {0x00000030, 0x00020085}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000000}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x000010f0, 0x00000100}, - {0x00001270, 0x00000000}, - {0x000012b0, 0x00000000}, - {0x000012f0, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00008000, 0x00000000}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000000}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008040, 0x00000000}, - {0x00008044, 0x00000000}, - {0x00008048, 0x00000000}, - {0x0000804c, 0xffffffff}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000310}, - {0x00008074, 0x00000020}, - {0x00008078, 0x00000000}, - {0x0000809c, 0x0000000f}, - {0x000080a0, 0x00000000}, - {0x000080a4, 0x02ff0000}, - {0x000080a8, 0x0e070605}, - {0x000080ac, 0x0000000d}, - {0x000080b0, 0x00000000}, - {0x000080b4, 0x00000000}, - {0x000080b8, 0x00000000}, - {0x000080bc, 0x00000000}, - {0x000080c0, 0x2a800000}, - {0x000080c4, 0x06900168}, - {0x000080c8, 0x13881c20}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00252500}, - {0x000080d4, 0x00a00000}, - {0x000080d8, 0x00400000}, - {0x000080dc, 0x00000000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x3f3f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00000000}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000000}, - {0x00008114, 0x000007ff}, - {0x00008118, 0x000000aa}, - {0x0000811c, 0x00003210}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x0000ffff}, - {0x00008144, 0xffffffff}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x00008170, 0x18486200}, - {0x00008174, 0x33332210}, - {0x00008178, 0x00000000}, - {0x0000817c, 0x00020000}, - {0x000081c0, 0x00000000}, - {0x000081c4, 0x33332210}, - {0x000081c8, 0x00000000}, - {0x000081cc, 0x00000000}, - {0x000081d4, 0x00000000}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f424}, - {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e848}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x40000000}, - {0x00008260, 0x00080922}, - {0x00008264, 0x9d400010}, - {0x00008268, 0xffffffff}, - {0x0000826c, 0x0000ffff}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000004}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x000000ff}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00000140}, - {0x00008314, 0x00000000}, - {0x0000831c, 0x0000010d}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000007}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000700}, - {0x00008338, 0x00ff0000}, - {0x0000833c, 0x02400000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0xaa48105b}, - {0x00008348, 0x008f0000}, - {0x0000835c, 0x00000000}, - {0x00008360, 0xffffffff}, - {0x00008364, 0xffffffff}, - {0x00008368, 0x00000000}, - {0x00008370, 0x00000000}, - {0x00008374, 0x000000ff}, - {0x00008378, 0x00000000}, - {0x0000837c, 0x00000000}, - {0x00008380, 0xffffffff}, - {0x00008384, 0xffffffff}, - {0x00008390, 0xffffffff}, - {0x00008394, 0xffffffff}, - {0x00008398, 0x00000000}, - {0x0000839c, 0x00000000}, - {0x000083a0, 0x00000000}, - {0x000083a4, 0x0000fa14}, - {0x000083a8, 0x000f0c00}, - {0x000083ac, 0x33332210}, - {0x000083b0, 0x33332210}, - {0x000083b4, 0x33332210}, - {0x000083b8, 0x33332210}, - {0x000083bc, 0x00000000}, - {0x000083c0, 0x00000000}, - {0x000083c4, 0x00000000}, - {0x000083c8, 0x00000000}, - {0x000083cc, 0x00000200}, - {0x000083d0, 0x000301ff}, -}; - -static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9340_1p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x000040a4, 0x00a0c1c9}, - {0x00007008, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, -}; - -#endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index fbdde29f0ab8..71cc0a3a29fb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -17,6 +17,931 @@ #ifndef INITVALS_9485_H #define INITVALS_9485_H +static const u32 ar9485Common_1_0[][2] = { + /* Addr allmodes */ + {0x00007010, 0x00000022}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, +}; + +static const u32 ar9485_1_0_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10212e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485Common_wo_xlna_rx_gain_1_0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x03850384}, + {0x0000a030, 0x03890388}, + {0x0000a034, 0x038b038a}, + {0x0000a038, 0x038d038c}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x28282828}, + {0x0000a088, 0x28282828}, + {0x0000a08c, 0x28282828}, + {0x0000a090, 0x28282828}, + {0x0000a094, 0x21212128}, + {0x0000a098, 0x171c1c1c}, + {0x0000a09c, 0x02020212}, + {0x0000a0a0, 0x00000202}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x111f1100}, + {0x0000a0c8, 0x111d111e}, + {0x0000a0cc, 0x111b111c}, + {0x0000a0d0, 0x22032204}, + {0x0000a0d4, 0x22012202}, + {0x0000a0d8, 0x221f2200}, + {0x0000a0dc, 0x221d221e}, + {0x0000a0e0, 0x33013302}, + {0x0000a0e4, 0x331f3300}, + {0x0000a0e8, 0x4402331e}, + {0x0000a0ec, 0x44004401}, + {0x0000a0f0, 0x441e441f}, + {0x0000a0f4, 0x55015502}, + {0x0000a0f8, 0x551f5500}, + {0x0000a0fc, 0x6602551e}, + {0x0000a100, 0x66006601}, + {0x0000a104, 0x661e661f}, + {0x0000a108, 0x7703661d}, + {0x0000a10c, 0x77017702}, + {0x0000a110, 0x00007700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x111f1100}, + {0x0000a148, 0x111d111e}, + {0x0000a14c, 0x111b111c}, + {0x0000a150, 0x22032204}, + {0x0000a154, 0x22012202}, + {0x0000a158, 0x221f2200}, + {0x0000a15c, 0x221d221e}, + {0x0000a160, 0x33013302}, + {0x0000a164, 0x331f3300}, + {0x0000a168, 0x4402331e}, + {0x0000a16c, 0x44004401}, + {0x0000a170, 0x441e441f}, + {0x0000a174, 0x55015502}, + {0x0000a178, 0x551f5500}, + {0x0000a17c, 0x6602551e}, + {0x0000a180, 0x66006601}, + {0x0000a184, 0x661e661f}, + {0x0000a188, 0x7703661d}, + {0x0000a18c, 0x77017702}, + {0x0000a190, 0x00007700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000296}, +}; + +static const u32 ar9485Modes_high_power_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485_1_0[][2] = { + /* Addr allmodes */ + {0x0000a580, 0x00000000}, + {0x0000a584, 0x00000000}, + {0x0000a588, 0x00000000}, + {0x0000a58c, 0x00000000}, + {0x0000a590, 0x00000000}, + {0x0000a594, 0x00000000}, + {0x0000a598, 0x00000000}, + {0x0000a59c, 0x00000000}, + {0x0000a5a0, 0x00000000}, + {0x0000a5a4, 0x00000000}, + {0x0000a5a8, 0x00000000}, + {0x0000a5ac, 0x00000000}, + {0x0000a5b0, 0x00000000}, + {0x0000a5b4, 0x00000000}, + {0x0000a5b8, 0x00000000}, + {0x0000a5bc, 0x00000000}, +}; + +static const u32 ar9485_1_0_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73800000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x00016048, 0x6c92426e}, + {0x0001604c, 0x000f0278}, + {0x00016050, 0x6db6db6c}, + {0x00016054, 0x6db60000}, + {0x00016080, 0x00080000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x14214514}, + {0x0001608c, 0x119f081e}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd28b3330}, + {0x000160a0, 0xc2108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92480040}, + {0x000160c0, 0x006db6db}, + {0x000160c4, 0x0186db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x6de6fbe0}, + {0x000160d0, 0xf7dfcf3c}, + {0x00016100, 0x04cb0001}, + {0x00016104, 0xfff80015}, + {0x00016108, 0x00080010}, + {0x00016144, 0x01884080}, + {0x00016148, 0x00008040}, + {0x00016180, 0x08453333}, + {0x00016184, 0x18e82f01}, + {0x00016188, 0x00000000}, + {0x0001618c, 0x00000000}, + {0x00016240, 0x08400000}, + {0x00016244, 0x1bf90f00}, + {0x00016248, 0x00000000}, + {0x0001624c, 0x00000000}, + {0x00016280, 0x01000015}, + {0x00016284, 0x00d30000}, + {0x00016288, 0x00318000}, + {0x0001628c, 0x50000000}, + {0x00016290, 0x4b96210f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016c40, 0x1319c178}, + {0x00016c44, 0x10000000}, +}; + +static const u32 ar9485Modes_lowest_ob_db_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485_1_0_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a8f6b}, + {0x0000980c, 0x04800000}, + {0x00009814, 0x9280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x5f3ca3de}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x14750600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x52440bbe}, + {0x000098bc, 0x00000002}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009c04, 0x00000000}, + {0x00009c08, 0x03200000}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x1883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c00400}, + {0x00009d18, 0x00000000}, + {0x00009d1c, 0x00000000}, + {0x00009e08, 0x0038233c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0a6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e40, 0x0d261820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009fc0, 0x80be4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x0000a20c, 0x00000000}, + {0x0000a210, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2dc, 0x00000000}, + {0x0000a2e0, 0x00000000}, + {0x0000a2e4, 0x00000000}, + {0x0000a2e8, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000006}, + {0x0000a3f8, 0x0cdbd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d0011ce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00000000}, + {0x0000a440, 0x00000000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x04000000}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a458, 0x00000000}, + {0x0000a5c4, 0x3fad9d74}, + {0x0000a5c8, 0x0048060a}, + {0x0000a5cc, 0x00000637}, + {0x0000a760, 0x03020100}, + {0x0000a764, 0x09080504}, + {0x0000a768, 0x0d0c0b0a}, + {0x0000a76c, 0x13121110}, + {0x0000a770, 0x31301514}, + {0x0000a774, 0x35343332}, + {0x0000a778, 0x00000036}, + {0x0000a780, 0x00000838}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000001}, +}; + +static const u32 ar9485Modes_high_ob_db_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485Common_rx_gain_1_0[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x01800082}, + {0x0000a014, 0x01820181}, + {0x0000a018, 0x01840183}, + {0x0000a01c, 0x01880185}, + {0x0000a020, 0x018a0189}, + {0x0000a024, 0x02850284}, + {0x0000a028, 0x02890288}, + {0x0000a02c, 0x03850384}, + {0x0000a030, 0x03890388}, + {0x0000a034, 0x038b038a}, + {0x0000a038, 0x038d038c}, + {0x0000a03c, 0x03910390}, + {0x0000a040, 0x03930392}, + {0x0000a044, 0x03950394}, + {0x0000a048, 0x00000396}, + {0x0000a04c, 0x00000000}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x28282828}, + {0x0000a084, 0x28282828}, + {0x0000a088, 0x28282828}, + {0x0000a08c, 0x28282828}, + {0x0000a090, 0x28282828}, + {0x0000a094, 0x21212128}, + {0x0000a098, 0x171c1c1c}, + {0x0000a09c, 0x02020212}, + {0x0000a0a0, 0x00000202}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x111f1100}, + {0x0000a0c8, 0x111d111e}, + {0x0000a0cc, 0x111b111c}, + {0x0000a0d0, 0x22032204}, + {0x0000a0d4, 0x22012202}, + {0x0000a0d8, 0x221f2200}, + {0x0000a0dc, 0x221d221e}, + {0x0000a0e0, 0x33013302}, + {0x0000a0e4, 0x331f3300}, + {0x0000a0e8, 0x4402331e}, + {0x0000a0ec, 0x44004401}, + {0x0000a0f0, 0x441e441f}, + {0x0000a0f4, 0x55015502}, + {0x0000a0f8, 0x551f5500}, + {0x0000a0fc, 0x6602551e}, + {0x0000a100, 0x66006601}, + {0x0000a104, 0x661e661f}, + {0x0000a108, 0x7703661d}, + {0x0000a10c, 0x77017702}, + {0x0000a110, 0x00007700}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x111f1100}, + {0x0000a148, 0x111d111e}, + {0x0000a14c, 0x111b111c}, + {0x0000a150, 0x22032204}, + {0x0000a154, 0x22012202}, + {0x0000a158, 0x221f2200}, + {0x0000a15c, 0x221d221e}, + {0x0000a160, 0x33013302}, + {0x0000a164, 0x331f3300}, + {0x0000a168, 0x4402331e}, + {0x0000a16c, 0x44004401}, + {0x0000a170, 0x441e441f}, + {0x0000a174, 0x55015502}, + {0x0000a178, 0x551f5500}, + {0x0000a17c, 0x6602551e}, + {0x0000a180, 0x66006601}, + {0x0000a184, 0x661e661f}, + {0x0000a188, 0x7703661d}, + {0x0000a18c, 0x77017702}, + {0x0000a190, 0x00007700}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000296}, +}; + +static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10252e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10253e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485_1_0_soc_preamble[][2] = { + /* Addr allmodes */ + {0x00004090, 0x00aa10aa}, + {0x000040a4, 0x00a0c9c9}, + {0x00007048, 0x00000004}, +}; + +static const u32 ar9485_fast_clock_1_0_baseband_postamble[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00009e00, 0x03721821, 0x03721821}, + {0x0000a230, 0x0000400b, 0x00004016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9485_1_0_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, + {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, + {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, + {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, + {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, + {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, + {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, + {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, + {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, + {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, + {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, + {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, + {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const u32 ar9485Modes_low_ob_db_tx_gain_1_0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, + {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, + {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, + {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, + {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, + {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, + {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, + {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, + {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, + {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, + {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, + {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, + {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, + {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, + {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, + {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, + {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, + {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, + {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, + {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, + {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, + {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, + {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, + {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, + {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, + {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, + {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, + {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, +}; + +static const u32 ar9485_1_0_pcie_phy_clkreq_disable_L1[][2] = { + /* Addr allmodes */ + {0x00018c00, 0x10213e5e}, + {0x00018c04, 0x000801d8}, + {0x00018c08, 0x0000580c}, +}; + +static const u32 ar9485_1_0_radio_postamble[][2] = { + /* Addr allmodes */ + {0x0001609c, 0x0b283f31}, + {0x000160ac, 0x24611800}, + {0x000160b0, 0x03284f3e}, + {0x0001610c, 0x00170000}, + {0x00016140, 0x10804008}, +}; + +static const u32 ar9485_1_0_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x00020085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00000000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c20}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00a00000}, + {0x000080d8, 0x00400000}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18486200}, + {0x00008174, 0x33332210}, + {0x00008178, 0x00000000}, + {0x0000817c, 0x00020000}, + {0x000081c0, 0x00000000}, + {0x000081c4, 0x33332210}, + {0x000081c8, 0x00000000}, + {0x000081cc, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f400}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e800}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x9ca00010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x00000007}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0x00ff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xa248105b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a0, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; + static const u32 ar9485_1_1_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, @@ -396,7 +1321,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -469,7 +1394,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -635,7 +1560,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -728,7 +1653,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -827,7 +1752,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, - {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, + {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 0312aa091807..099bd4183ad0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -120,11 +120,13 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, /* RX / TX */ /***********/ +#define ATH_MAX_ANTENNA 3 #define ATH_RXBUF 512 #define ATH_TXBUF 512 #define ATH_TXBUF_RESERVE 5 #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) #define ATH_TXMAXTRY 13 +#define ATH_MGT_TXMAXTRY 4 #define TID_TO_WME_AC(_tid) \ ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ @@ -200,7 +202,6 @@ struct ath_atx_ac { int sched; struct list_head list; struct list_head tid_q; - bool clear_ps_filter; }; struct ath_frame_info { @@ -256,12 +257,8 @@ struct ath_node { #endif struct ath_atx_tid tid[WME_NUM_TID]; struct ath_atx_ac ac[WME_NUM_AC]; - int ps_key; - u16 maxampdu; u8 mpdudensity; - - bool sleeping; }; #define AGGR_CLEANUP BIT(1) @@ -343,18 +340,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); -void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); -bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); - /********/ /* VIFs */ /********/ struct ath_vif { int av_bslot; - bool is_bslot_active, primary_sta_vif; + bool is_bslot_active; __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ + enum nl80211_iftype av_opmode; struct ath_buf *av_bcbuf; + u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ }; /*******************/ @@ -366,7 +362,7 @@ struct ath_vif { * number of BSSIDs) if a given beacon does not go out even after waiting this * number of beacon intervals, the game's up. */ -#define BSTUCK_THRESH 9 +#define BSTUCK_THRESH (9 * ATH_BCBUF) #define ATH_BCBUF 4 #define ATH_DEFAULT_BINTVAL 100 /* TU */ #define ATH_DEFAULT_BMISS_LIMIT 10 @@ -390,7 +386,7 @@ struct ath_beacon { u32 beaconq; u32 bmisscnt; u32 ast_be_xmit; - u32 bc_tstamp; + u64 bc_tstamp; struct ieee80211_vif *bslot[ATH_BCBUF]; int slottime; int slotupdate; @@ -405,7 +401,6 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); int ath_beaconq_config(struct ath_softc *sc); -void ath_set_beacon(struct ath_softc *sc); void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); /*******/ @@ -423,7 +418,6 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); #define ATH_PAPRD_TIMEOUT 100 /* msecs */ void ath_hw_check(struct work_struct *work); -void ath_hw_pll_work(struct work_struct *work); void ath_paprd_calibrate(struct work_struct *work); void ath_ani_calibrate(unsigned long data); @@ -454,7 +448,6 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); #define ATH_LED_PIN_DEF 1 #define ATH_LED_PIN_9287 8 -#define ATH_LED_PIN_9300 10 #define ATH_LED_PIN_9485 6 #ifdef CONFIG_MAC80211_LEDS @@ -557,7 +550,6 @@ struct ath_ant_comb { #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) #define SC_OP_ENABLE_APM BIT(15) -#define SC_OP_PRIM_STA_VIF BIT(16) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@ -675,7 +667,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); bool ath9k_uses_beacons(int type); -#ifdef CONFIG_ATH9K_PCI +#ifdef CONFIG_PCI int ath_pci_init(void); void ath_pci_exit(void); #else @@ -683,7 +675,7 @@ static inline int ath_pci_init(void) { return 0; }; static inline void ath_pci_exit(void) {}; #endif -#ifdef CONFIG_ATH9K_AHB +#ifdef CONFIG_ATHEROS_AR71XX int ath_ahb_init(void); void ath_ahb_exit(void); #else @@ -696,6 +688,8 @@ void ath9k_ps_restore(struct ath_softc *sc); u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); +void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); + void ath_start_rfkill_poll(struct ath_softc *sc); extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); void ath9k_calculate_iter_data(struct ieee80211_hw *hw, diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c index 22cd241a098b..6d2a545fc35e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c @@ -57,8 +57,8 @@ int ath_beaconq_config(struct ath_softc *sc) /* * Associates the beacon frame buffer with a transmit descriptor. Will set - * up rate codes, and channel flags. Beacons are always sent out at the - * lowest rate, and are not retried. + * up all required antenna switch parameters, rate codes, and channel flags. + * Beacons are always sent out at the lowest rate, and are not retried. */ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_buf *bf, int rateidx) @@ -68,7 +68,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_common *common = ath9k_hw_common(ah); struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; - int flags, ctsrate = 0, ctsduration = 0; + int flags, antenna, ctsrate = 0, ctsduration = 0; struct ieee80211_supported_band *sband; u8 rate = 0; @@ -76,6 +76,12 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, flags = ATH9K_TXDESC_NOACK; ds->ds_link = 0; + /* + * Switch antenna every beacon. + * Should only switch every beacon period, not for every SWBA + * XXX assumes two antennae + */ + antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); sband = &sc->sbands[common->hw->conf.channel->band]; rate = sband->bitrates[rateidx].hw_value; @@ -272,7 +278,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) return -ENOMEM; tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); + sc->beacon.bc_tstamp = le64_to_cpu(tstamp); /* Calculate a TSF adjustment factor required for staggered beacons. */ if (avp->av_bslot > 0) { u64 tsfadjust; @@ -288,8 +294,8 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) * adjustment. Other slots are adjusted to get the timestamp * close to the TBTT for the BSS. */ - tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; - avp->tsf_adjust = cpu_to_le64(tsfadjust); + tsfadjust = intval * avp->av_bslot / ATH_BCBUF; + avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); ath_dbg(common, ATH_DBG_BEACON, "stagger beacons, bslot %d intval %u tsfadjust %llu\n", @@ -320,11 +326,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) if (avp->av_bcbuf != NULL) { struct ath_buf *bf; - avp->is_bslot_active = false; if (avp->av_bslot != -1) { sc->beacon.bslot[avp->av_bslot] = NULL; sc->nbcnvifs--; - avp->av_bslot = -1; } bf = avp->av_bcbuf; @@ -365,13 +369,12 @@ void ath_beacon_tasklet(unsigned long data) if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { sc->beacon.bmisscnt++; - if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { + if (sc->beacon.bmisscnt < BSTUCK_THRESH) { ath_dbg(common, ATH_DBG_BSTUCK, "missed %u consecutive beacons\n", sc->beacon.bmisscnt); ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); - if (sc->beacon.bmisscnt > 3) - ath9k_hw_bstuck_nfcal(ah); + ath9k_hw_bstuck_nfcal(ah); } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { ath_dbg(common, ATH_DBG_BSTUCK, "beacon is officially stuck\n"); @@ -382,6 +385,13 @@ void ath_beacon_tasklet(unsigned long data) return; } + if (sc->beacon.bmisscnt != 0) { + ath_dbg(common, ATH_DBG_BSTUCK, + "resume beacon xmit after %u misses\n", + sc->beacon.bmisscnt); + sc->beacon.bmisscnt = 0; + } + /* * Generate beacon frames. we are sending frames * staggered so calculate the slot for this frame based @@ -391,14 +401,21 @@ void ath_beacon_tasklet(unsigned long data) intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; tsf = ath9k_hw_gettsf64(ah); - tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); - tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); - slot = (tsftu % (intval * ATH_BCBUF)) / intval; + tsftu = TSF_TO_TU(tsf>>32, tsf); + slot = ((tsftu % intval) * ATH_BCBUF) / intval; + /* + * Reverse the slot order to get slot 0 on the TBTT offset that does + * not require TSF adjustment and other slots adding + * slot/ATH_BCBUF * beacon_int to timestamp. For example, with + * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. + * and slot 0 is at correct offset to TBTT. + */ + slot = ATH_BCBUF - slot - 1; vif = sc->beacon.bslot[slot]; ath_dbg(common, ATH_DBG_BEACON, "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu / ATH_BCBUF, intval, vif); + slot, tsf, tsftu, intval, vif); bfaddr = 0; if (vif) { @@ -407,13 +424,6 @@ void ath_beacon_tasklet(unsigned long data) bfaddr = bf->bf_daddr; bc = 1; } - - if (sc->beacon.bmisscnt != 0) { - ath_dbg(common, ATH_DBG_BSTUCK, - "resume beacon xmit after %u misses\n", - sc->beacon.bmisscnt); - sc->beacon.bmisscnt = 0; - } } /* @@ -453,17 +463,13 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 next_beacon, u32 beacon_period) { - if (sc->sc_flags & SC_OP_TSF_RESET) { + if (beacon_period & ATH9K_BEACON_RESET_TSF) ath9k_ps_wakeup(sc); - ath9k_hw_reset_tsf(sc->sc_ah); - } ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); - if (sc->sc_flags & SC_OP_TSF_RESET) { + if (beacon_period & ATH9K_BEACON_RESET_TSF) ath9k_ps_restore(sc); - sc->sc_flags &= ~SC_OP_TSF_RESET; - } } /* @@ -478,14 +484,18 @@ static void ath_beacon_config_ap(struct ath_softc *sc, u32 nexttbtt, intval; /* NB: the beacon interval is kept internally in TU's */ - intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); + intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; intval /= ATH_BCBUF; /* for staggered beacons */ nexttbtt = intval; + if (sc->sc_flags & SC_OP_TSF_RESET) + intval |= ATH9K_BEACON_RESET_TSF; + /* * In AP mode we enable the beacon timers and SWBA interrupts to * prepare beacon frames. */ + intval |= ATH9K_BEACON_ENA; ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); @@ -495,6 +505,11 @@ static void ath_beacon_config_ap(struct ath_softc *sc, ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah, ah->imask); + + /* Clear the reset TSF flag, so that subsequent beacon updation + will not reset the HW TSF. */ + + sc->sc_flags &= ~SC_OP_TSF_RESET; } /* @@ -628,20 +643,25 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - u32 tsf, delta, intval, nexttbtt; - - tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); - intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); - - if (!sc->beacon.bc_tstamp) - nexttbtt = tsf + intval; - else { - if (tsf > sc->beacon.bc_tstamp) - delta = (tsf - sc->beacon.bc_tstamp); - else - delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); - nexttbtt = tsf + roundup(delta, intval); - } + u64 tsf; + u32 tsftu, intval, nexttbtt; + + intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; + + + /* Pull nexttbtt forward to reflect the current TSF */ + + nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); + if (nexttbtt == 0) + nexttbtt = intval; + else if (intval) + nexttbtt = roundup(nexttbtt, intval); + + tsf = ath9k_hw_gettsf64(ah); + tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; + do { + nexttbtt += intval; + } while (nexttbtt < tsftu); ath_dbg(common, ATH_DBG_BEACON, "IBSS nexttbtt %u intval %u (%u)\n", @@ -652,6 +672,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, * if we need to manually prepare beacon frames. Otherwise we use a * self-linked tx descriptor and let the hardware deal with things. */ + intval |= ATH9K_BEACON_ENA; ah->imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); @@ -664,63 +685,22 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, ath9k_hw_set_interrupts(ah, ah->imask); } -static bool ath9k_allow_beacon_config(struct ath_softc *sc, - struct ieee80211_vif *vif) +void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) { struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct ath_vif *avp = (void *)vif->drv_priv; + enum nl80211_iftype iftype; - /* - * Can not have different beacon interval on multiple - * AP interface case - */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && - (sc->nbcnvifs > 1) && - (vif->type == NL80211_IFTYPE_AP) && - (cur_conf->beacon_interval != bss_conf->beacon_int)) { - ath_dbg(common, ATH_DBG_CONFIG, - "Changing beacon interval of multiple \ - AP interfaces !\n"); - return false; - } - /* - * Can not configure station vif's beacon config - * while on AP opmode - */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && - (vif->type != NL80211_IFTYPE_AP)) { - ath_dbg(common, ATH_DBG_CONFIG, - "STA vif's beacon not allowed on AP mode\n"); - return false; - } - /* - * Do not allow beacon config if HW was already configured - * with another STA vif - */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && - (vif->type == NL80211_IFTYPE_STATION) && - (sc->sc_flags & SC_OP_BEACONS) && - !avp->primary_sta_vif) { - ath_dbg(common, ATH_DBG_CONFIG, - "Beacon already configured for a station interface\n"); - return false; + /* Setup the beacon configuration parameters */ + if (vif) { + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + iftype = vif->type; + cur_conf->beacon_interval = bss_conf->beacon_int; + cur_conf->dtim_period = bss_conf->dtim_period; + } else { + iftype = sc->sc_ah->opmode; } - return true; -} - -void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) -{ - struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - - if (!ath9k_allow_beacon_config(sc, vif)) - return; - /* Setup the beacon configuration parameters */ - cur_conf->beacon_interval = bss_conf->beacon_int; - cur_conf->dtim_period = bss_conf->dtim_period; cur_conf->listen_interval = 1; cur_conf->dtim_count = 1; cur_conf->bmiss_timeout = @@ -743,37 +723,9 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) if (cur_conf->dtim_period == 0) cur_conf->dtim_period = 1; - ath_set_beacon(sc); -} - -static bool ath_has_valid_bslot(struct ath_softc *sc) -{ - struct ath_vif *avp; - int slot; - bool found = false; - - for (slot = 0; slot < ATH_BCBUF; slot++) { - if (sc->beacon.bslot[slot]) { - avp = (void *)sc->beacon.bslot[slot]->drv_priv; - if (avp->is_bslot_active) { - found = true; - break; - } - } - } - return found; -} - - -void ath_set_beacon(struct ath_softc *sc) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; - - switch (sc->sc_ah->opmode) { + switch (iftype) { case NL80211_IFTYPE_AP: - if (ath_has_valid_bslot(sc)) - ath_beacon_config_ap(sc, cur_conf); + ath_beacon_config_ap(sc, cur_conf); break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: @@ -794,15 +746,26 @@ void ath_set_beacon(struct ath_softc *sc) void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) { struct ath_hw *ah = sc->sc_ah; - - if (!ath_has_valid_bslot(sc)) - return; + struct ath_vif *avp; + int slot; + bool found = false; ath9k_ps_wakeup(sc); if (status) { - /* Re-enable beaconing */ - ah->imask |= ATH9K_INT_SWBA; - ath9k_hw_set_interrupts(ah, ah->imask); + for (slot = 0; slot < ATH_BCBUF; slot++) { + if (sc->beacon.bslot[slot]) { + avp = (void *)sc->beacon.bslot[slot]->drv_priv; + if (avp->is_bslot_active) { + found = true; + break; + } + } + } + if (found) { + /* Re-enable beaconing */ + ah->imask |= ATH9K_INT_SWBA; + ath9k_hw_set_interrupts(ah, ah->imask); + } } else { /* Disable SWBA interrupt */ ah->imask &= ~ATH9K_INT_SWBA; diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c index 23f15a7ca7f1..d33bf204c995 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c @@ -51,10 +51,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) .bt_hold_rx_clear = true, }; u32 i; - bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; - - if (AR_SREV_9300_20_OR_LATER(ah)) - rxclear_polarity = !ath_bt_config.bt_rxclear_polarity; btcoex_hw->bt_coex_mode = (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | @@ -63,7 +59,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | SM(ath_bt_config.bt_mode, AR_BT_MODE) | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | - SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | + SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | SM(qnum, AR_BT_QCU_THRESH); @@ -146,7 +142,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, } EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); - static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) { struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; @@ -157,22 +152,9 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) * enable coex 3-wire */ REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); + REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); - - if (AR_SREV_9300_20_OR_LATER(ah)) { - REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ah->bt_coex_wlan_weight[0]); - REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ah->bt_coex_wlan_weight[1]); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ah->bt_coex_bt_weight[0]); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ah->bt_coex_bt_weight[1]); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ah->bt_coex_bt_weight[2]); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ah->bt_coex_bt_weight[3]); - - } else - REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); - - - if (AR_SREV_9271(ah)) { val = REG_READ(ah, 0x50040); val &= 0xFFFFFEFF; @@ -220,86 +202,10 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); + REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); REG_WRITE(ah, AR_BT_COEX_MODE2, 0); - - if (AR_SREV_9300_20_OR_LATER(ah)) { - REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0); - REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0); - REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0); - } else - REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); - } ah->btcoex_hw.enabled = false; } EXPORT_SYMBOL(ath9k_hw_btcoex_disable); - -static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, - enum ath_stomp_type stomp_type) -{ - ah->bt_coex_bt_weight[0] = AR9300_BT_WGHT; - ah->bt_coex_bt_weight[1] = AR9300_BT_WGHT; - ah->bt_coex_bt_weight[2] = AR9300_BT_WGHT; - ah->bt_coex_bt_weight[3] = AR9300_BT_WGHT; - - - switch (stomp_type) { - case ATH_BTCOEX_STOMP_ALL: - ah->bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0; - ah->bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1; - break; - case ATH_BTCOEX_STOMP_LOW: - ah->bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0; - ah->bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1; - break; - case ATH_BTCOEX_STOMP_NONE: - ah->bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0; - ah->bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1; - break; - - default: - ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Invalid Stomptype\n"); - break; - } - - ath9k_hw_btcoex_enable(ah); -} - -/* - * Configures appropriate weight based on stomp type. - */ -void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, - enum ath_stomp_type stomp_type) -{ - if (AR_SREV_9300_20_OR_LATER(ah)) { - ar9003_btcoex_bt_stomp(ah, stomp_type); - return; - } - - switch (stomp_type) { - case ATH_BTCOEX_STOMP_ALL: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_LOW: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_NONE: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT); - break; - default: - ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Invalid Stomptype\n"); - break; - } - - ath9k_hw_btcoex_enable(ah); -} -EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h index a9efca83d676..588dfd464dd1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h @@ -19,13 +19,9 @@ #include "hw.h" -#define ATH_WLANACTIVE_GPIO_9280 5 -#define ATH_BTACTIVE_GPIO_9280 6 -#define ATH_BTPRIORITY_GPIO_9285 7 - -#define ATH_WLANACTIVE_GPIO_9300 5 -#define ATH_BTACTIVE_GPIO_9300 4 -#define ATH_BTPRIORITY_GPIO_9300 8 +#define ATH_WLANACTIVE_GPIO 5 +#define ATH_BTACTIVE_GPIO 6 +#define ATH_BTPRIORITY_GPIO 7 #define ATH_BTCOEX_DEF_BT_PERIOD 45 #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 @@ -36,14 +32,6 @@ #define ATH_BT_CNT_THRESHOLD 3 #define ATH_BT_CNT_SCAN_THRESHOLD 15 -/* Defines the BT AR_BT_COEX_WGHT used */ -enum ath_stomp_type { - ATH_BTCOEX_NO_STOMP, - ATH_BTCOEX_STOMP_ALL, - ATH_BTCOEX_STOMP_LOW, - ATH_BTCOEX_STOMP_NONE -}; - enum ath_btcoex_scheme { ATH_BTCOEX_CFG_NONE, ATH_BTCOEX_CFG_2WIRE, @@ -69,7 +57,5 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, u32 wlan_weight); void ath9k_hw_btcoex_enable(struct ath_hw *ah); void ath9k_hw_btcoex_disable(struct ath_hw *ah); -void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, - enum ath_stomp_type stomp_type); #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.c b/trunk/drivers/net/wireless/ath/ath9k/common.c index 74535e6dfb82..615e68276e72 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.c +++ b/trunk/drivers/net/wireless/ath/ath9k/common.c @@ -116,7 +116,7 @@ void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, if (chan->band == IEEE80211_BAND_2GHZ) { ichan->chanmode = CHANNEL_G; - ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; + ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; } else { ichan->chanmode = CHANNEL_A; ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; @@ -158,6 +158,37 @@ int ath9k_cmn_count_streams(unsigned int chainmask, int max) } EXPORT_SYMBOL(ath9k_cmn_count_streams); +/* + * Configures appropriate weight based on stomp type. + */ +void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, + enum ath_stomp_type stomp_type) +{ + struct ath_hw *ah = common->ah; + + switch (stomp_type) { + case ATH_BTCOEX_STOMP_ALL: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_ALL_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_LOW: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_NONE: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_NONE_WLAN_WGHT); + break; + default: + ath_dbg(common, ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); + break; + } + + ath9k_hw_btcoex_enable(ah); +} +EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); + void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, u16 new_txpow, u16 *txpower) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.h b/trunk/drivers/net/wireless/ath/ath9k/common.h index 5124f1420b3a..b2f7b5f89097 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.h +++ b/trunk/drivers/net/wireless/ath/ath9k/common.h @@ -50,6 +50,14 @@ #define ATH_EP_RND(x, mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +/* Defines the BT AR_BT_COEX_WGHT used */ +enum ath_stomp_type { + ATH_BTCOEX_NO_STOMP, + ATH_BTCOEX_STOMP_ALL, + ATH_BTCOEX_STOMP_LOW, + ATH_BTCOEX_STOMP_NONE +}; + int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index bad1a87249b6..8df5a92a20f1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -326,8 +326,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) sc->debug.stats.istats.dtimsync++; if (status & ATH9K_INT_DTIM) sc->debug.stats.istats.dtim++; - if (status & ATH9K_INT_TSFOOR) - sc->debug.stats.istats.tsfoor++; } static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, @@ -381,12 +379,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor); len += snprintf(buf + len, sizeof(buf) - len, "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); - if (len > sizeof(buf)) len = sizeof(buf); @@ -850,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, struct ath_softc *sc = file->private_data; char *buf; - unsigned int len = 0, size = 1400; + unsigned int len = 0, size = 1152; ssize_t retval = 0; buf = kzalloc(size, GFP_KERNEL); @@ -879,34 +874,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, "%18s : %10u\n", "DECRYPT BUSY ERR", sc->debug.stats.rxstats.decrypt_busy_err); - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "RSSI-CTL0", - sc->debug.stats.rxstats.rs_rssi_ctl0); - - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "RSSI-CTL1", - sc->debug.stats.rxstats.rs_rssi_ctl1); - - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "RSSI-CTL2", - sc->debug.stats.rxstats.rs_rssi_ctl2); - - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "RSSI-EXT0", - sc->debug.stats.rxstats.rs_rssi_ext0); - - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "RSSI-EXT1", - sc->debug.stats.rxstats.rs_rssi_ext1); - - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "RSSI-EXT2", - sc->debug.stats.rxstats.rs_rssi_ext2); - - len += snprintf(buf + len, size - len, - "%18s : %10d\n", "Rx Antenna", - sc->debug.stats.rxstats.rs_antenna); - PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); @@ -981,16 +948,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) RX_PHY_ERR_INC(phyerr); } - sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; - sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1; - sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2; - - sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0; - sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1; - sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2; - - sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; - #undef RX_STAT_INC #undef RX_PHY_ERR_INC } @@ -1131,43 +1088,67 @@ int ath9k_init_debug(struct ath_hw *ah) return -ENOMEM; #ifdef CONFIG_ATH_DEBUG - debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - sc, &fops_debug); + if (!debugfs_create_file("debug", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_debug)) + goto err; #endif - debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_dma); - debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_interrupt); - debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - sc, &fops_wiphy); - debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_xmit); - debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_stations); - debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_misc); - debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_recv); - debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_rx_chainmask); - debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_tx_chainmask); - debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - sc, &fops_regidx); - debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - sc, &fops_regval); - debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, - &ah->config.cwm_ignore_extcca); - debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_regdump); - - debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); - - debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); + + if (!debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_dma)) + goto err; + + if (!debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_interrupt)) + goto err; + + if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_wiphy)) + goto err; + + if (!debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_xmit)) + goto err; + + if (!debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_stations)) + goto err; + + if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_misc)) + goto err; + + if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_recv)) + goto err; + + if (!debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_rx_chainmask)) + goto err; + + if (!debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_tx_chainmask)) + goto err; + + if (!debugfs_create_file("regidx", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_regidx)) + goto err; + + if (!debugfs_create_file("regval", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_regval)) + goto err; + + if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) + goto err; + + if (!debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, + sc, &fops_regdump)) + goto err; sc->debug.regidx = 0; return 0; +err: + debugfs_remove_recursive(sc->debug.debugfs_phy); + sc->debug.debugfs_phy = NULL; + return -ENOMEM; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index 5488a324cc10..59338de0ce19 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -54,9 +54,6 @@ struct ath_buf; * @dtimsync: DTIM sync lossage * @dtim: RX Beacon with DTIM * @bb_watchdog: Baseband watchdog - * @tsfoor: TSF out of range, indicates that the corrected TSF received - * from a beacon differs from the PCU's internal TSF by more than a - * (programmable) threshold */ struct ath_interrupt_stats { u32 total; @@ -81,7 +78,6 @@ struct ath_interrupt_stats { u32 dtimsync; u32 dtim; u32 bb_watchdog; - u32 tsfoor; }; /** @@ -161,13 +157,6 @@ struct ath_rx_stats { u32 post_delim_crc_err; u32 decrypt_busy_err; u32 phy_err_stats[ATH9K_PHYERR_MAX]; - int8_t rs_rssi_ctl0; - int8_t rs_rssi_ctl1; - int8_t rs_rssi_ctl2; - int8_t rs_rssi_ext0; - int8_t rs_rssi_ext1; - int8_t rs_rssi_ext2; - u8 rs_antenna; }; struct ath_stats { diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom.h b/trunk/drivers/net/wireless/ath/ath9k/eeprom.h index 3e316133f114..bd82447f5b78 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom.h @@ -436,11 +436,7 @@ struct modal_eep_4k_header { u8 db2_2:4, db2_3:4; u8 db2_4:4, reserved:4; #endif - u8 tx_diversity; - u8 flc_pwr_thresh; - u8 bb_scale_smrt_antenna; -#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f - u8 futureModal[1]; + u8 futureModal[4]; struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; } __packed; diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 6f714dd72365..bc77a308c901 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -781,7 +781,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, { struct modal_eep_4k_header *pModal; struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - struct base_eep_header_4k *pBase = &eep->baseEepHeader; u8 txRxAttenLocal; u8 ob[5], db1[5], db2[5]; u8 ant_div_control1, ant_div_control2; @@ -1004,31 +1003,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); } - if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { - u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & - EEP_4K_BB_DESIRED_SCALE_MASK); - if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { - u32 pwrctrl, mask, clr; - - mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); - pwrctrl = mask * bb_desired_scale; - clr = mask * 0x1f; - REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); - REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); - REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); - - mask = BIT(0)|BIT(5)|BIT(15); - pwrctrl = mask * bb_desired_scale; - clr = mask * 0x1f; - REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); - - mask = BIT(0)|BIT(5); - pwrctrl = mask * bb_desired_scale; - clr = mask * 0x1f; - REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); - REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); - } - } } static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c index b87db4763098..8cd8333cc086 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -319,9 +319,10 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, u16 numXpdGain, xpdMask; u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; u32 reg32, regOffset, regChainOffset, regval; - int16_t diff = 0; + int16_t modalIdx, diff = 0; struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; + modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; xpdMask = pEepData->modalHeader.xpdGain; if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= @@ -391,8 +392,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, numXpdGain); } - ENABLE_REGWRITE_BUFFER(ah); - if (i == 0) { if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { @@ -443,7 +442,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, regOffset += 4; } } - REGWRITE_BUFFER_FLUSH(ah); } } @@ -759,8 +757,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; } - ENABLE_REGWRITE_BUFFER(ah); - /* OFDM power per rate */ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, ATH9K_POW_SM(ratesArray[rate18mb], 24) @@ -844,7 +840,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); } - REGWRITE_BUFFER_FLUSH(ah); } static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, @@ -857,12 +852,35 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, { struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &eep->modalHeader; + u16 antWrites[AR9287_ANT_16S]; u32 regChainOffset, regval; u8 txRxAttenLocal; - int i; + int i, j, offset_num; pModal = &eep->modalHeader; + antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); + antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); + antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); + antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); + antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); + antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); + antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); + antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); + + offset_num = 8; + + for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { + antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); + antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); + antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); + antWrites[j++] = 0; + antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); + antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); + antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); + antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); + } + REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); for (i = 0; i < AR9287_MAX_CHAINS; i++) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c index c031854b569f..fccd87df7300 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -231,10 +231,6 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) integer = swab32(pModal->antCtrlChain[i]); pModal->antCtrlChain[i] = integer; } - for (i = 0; i < 3; i++) { - word = swab16(pModal->xpaBiasLvlFreq[i]); - pModal->xpaBiasLvlFreq[i] = word; - } for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { word = swab16(pModal->spurChans[i].spurChan); @@ -803,8 +799,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, pwr_table_offset, &diff); - ENABLE_REGWRITE_BUFFER(ah); - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { if (OLC_FOR_AR9280_20_LATER) { REG_WRITE(ah, @@ -853,7 +847,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, regOffset += 4; } - REGWRITE_BUFFER_FLUSH(ah); } } @@ -1212,8 +1205,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, } } - ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, ATH9K_POW_SM(ratesArray[rate18mb], 24) | ATH9K_POW_SM(ratesArray[rate12mb], 16) @@ -1300,8 +1291,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_POWER_TX_SUB, ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); - - REGWRITE_BUFFER_FLUSH(ah); } static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index 0349b3a1cc58..0fb8f8ac275a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -41,16 +41,12 @@ void ath_init_leds(struct ath_softc *sc) { int ret; - if (sc->sc_ah->led_pin < 0) { - if (AR_SREV_9287(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9485(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9485; - else if (AR_SREV_9300(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9300; - else - sc->sc_ah->led_pin = ATH_LED_PIN_DEF; - } + if (AR_SREV_9287(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9485(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9485; + else + sc->sc_ah->led_pin = ATH_LED_PIN_DEF; /* Configure gpio 1 for output */ ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, @@ -140,10 +136,10 @@ static void ath_detect_bt_priority(struct ath_softc *sc) static void ath9k_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, - u32 trig_timeout, + u32 timer_next, u32 timer_period) { - ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period); + ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { ath9k_hw_disable_interrupts(ah); @@ -176,17 +172,17 @@ static void ath_btcoex_period_timer(unsigned long data) struct ath_softc *sc = (struct ath_softc *) data; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_common *common = ath9k_hw_common(ah); u32 timer_period; bool is_btscan; - ath9k_ps_wakeup(sc); ath_detect_bt_priority(sc); is_btscan = sc->sc_flags & SC_OP_BT_SCAN; spin_lock_bh(&btcoex->btcoex_lock); - ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : + ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); spin_unlock_bh(&btcoex->btcoex_lock); @@ -197,12 +193,11 @@ static void ath_btcoex_period_timer(unsigned long data) timer_period = is_btscan ? btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp; - ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, + ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0, timer_period * 10); btcoex->hw_timer_enabled = true; } - ath9k_ps_restore(sc); mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); } @@ -222,16 +217,14 @@ static void ath_btcoex_no_stomp_timer(void *arg) ath_dbg(common, ATH_DBG_BTCOEX, "no stomp timer running\n"); - ath9k_ps_wakeup(sc); spin_lock_bh(&btcoex->btcoex_lock); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) - ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); spin_unlock_bh(&btcoex->btcoex_lock); - ath9k_ps_restore(sc); } int ath_init_btcoex_timer(struct ath_softc *sc) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c index 2e3a33a53406..2d10239ce829 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,9 +17,11 @@ #include "htc.h" /* identify firmware images */ -#define FIRMWARE_AR7010_1_1 "htc_7010.fw" -#define FIRMWARE_AR9271 "htc_9271.fw" +#define FIRMWARE_AR7010 "ar7010.fw" +#define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" +#define FIRMWARE_AR9271 "ar9271.fw" +MODULE_FIRMWARE(FIRMWARE_AR7010); MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); MODULE_FIRMWARE(FIRMWARE_AR9271); @@ -78,7 +80,7 @@ static void hif_usb_regout_cb(struct urb *urb) if (cmd) { ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, - cmd->skb, true); + cmd->skb, 1); kfree(cmd); } @@ -124,90 +126,6 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, return ret; } -static void hif_usb_mgmt_cb(struct urb *urb) -{ - struct cmd_buf *cmd = (struct cmd_buf *)urb->context; - struct hif_device_usb *hif_dev = cmd->hif_dev; - bool txok = true; - - if (!cmd || !cmd->skb || !cmd->hif_dev) - return; - - switch (urb->status) { - case 0: - break; - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - txok = false; - - /* - * If the URBs are being flushed, no need to complete - * this packet. - */ - spin_lock(&hif_dev->tx.tx_lock); - if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { - spin_unlock(&hif_dev->tx.tx_lock); - dev_kfree_skb_any(cmd->skb); - kfree(cmd); - return; - } - spin_unlock(&hif_dev->tx.tx_lock); - - break; - default: - txok = false; - break; - } - - skb_pull(cmd->skb, 4); - ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, - cmd->skb, txok); - kfree(cmd); -} - -static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, - struct sk_buff *skb) -{ - struct urb *urb; - struct cmd_buf *cmd; - int ret = 0; - __le16 *hdr; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (urb == NULL) - return -ENOMEM; - - cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); - if (cmd == NULL) { - usb_free_urb(urb); - return -ENOMEM; - } - - cmd->skb = skb; - cmd->hif_dev = hif_dev; - - hdr = (__le16 *) skb_push(skb, 4); - *hdr++ = cpu_to_le16(skb->len - 4); - *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); - - usb_fill_bulk_urb(urb, hif_dev->udev, - usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), - skb->data, skb->len, - hif_usb_mgmt_cb, cmd); - - usb_anchor_urb(urb, &hif_dev->mgmt_submitted); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - usb_unanchor_urb(urb); - kfree(cmd); - } - usb_free_urb(urb); - - return ret; -} - static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, struct sk_buff_head *list) { @@ -215,22 +133,7 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, while ((skb = __skb_dequeue(list)) != NULL) { dev_kfree_skb_any(skb); - } -} - -static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, - struct sk_buff_head *queue, - bool txok) -{ - struct sk_buff *skb; - - while ((skb = __skb_dequeue(queue)) != NULL) { - ath9k_htc_txcompletion_cb(hif_dev->htc_handle, - skb, txok); - if (txok) - TX_STAT_INC(skb_success); - else - TX_STAT_INC(skb_failed); + TX_STAT_INC(skb_dropped); } } @@ -238,7 +141,7 @@ static void hif_usb_tx_cb(struct urb *urb) { struct tx_buf *tx_buf = (struct tx_buf *) urb->context; struct hif_device_usb *hif_dev; - bool txok = true; + struct sk_buff *skb; if (!tx_buf || !tx_buf->hif_dev) return; @@ -252,7 +155,10 @@ static void hif_usb_tx_cb(struct urb *urb) case -ECONNRESET: case -ENODEV: case -ESHUTDOWN: - txok = false; + /* + * The URB has been killed, free the SKBs. + */ + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); /* * If the URBs are being flushed, no need to add this @@ -261,19 +167,41 @@ static void hif_usb_tx_cb(struct urb *urb) spin_lock(&hif_dev->tx.tx_lock); if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { spin_unlock(&hif_dev->tx.tx_lock); - ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); return; } spin_unlock(&hif_dev->tx.tx_lock); - break; + /* + * In the stop() case, this URB has to be added to + * the free list. + */ + goto add_free; default: - txok = false; break; } - ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok); + /* + * Check if TX has been stopped, this is needed because + * this CB could have been invoked just after the TX lock + * was released in hif_stop() and kill_urb() hasn't been + * called yet. + */ + spin_lock(&hif_dev->tx.tx_lock); + if (hif_dev->tx.flags & HIF_USB_TX_STOP) { + spin_unlock(&hif_dev->tx.tx_lock); + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); + goto add_free; + } + spin_unlock(&hif_dev->tx.tx_lock); + + /* Complete the queued SKBs. */ + while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { + ath9k_htc_txcompletion_cb(hif_dev->htc_handle, + skb, 1); + TX_STAT_INC(skb_completed); + } +add_free: /* Re-initialize the SKB queue */ tx_buf->len = tx_buf->offset = 0; __skb_queue_head_init(&tx_buf->skb_queue); @@ -346,7 +274,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); if (ret) { tx_buf->len = tx_buf->offset = 0; - ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false); + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); __skb_queue_head_init(&tx_buf->skb_queue); list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); hif_dev->tx.tx_buf_cnt++; @@ -358,11 +286,10 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) return ret; } -static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) +static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, + struct ath9k_htc_tx_ctl *tx_ctl) { - struct ath9k_htc_tx_ctl *tx_ctl; unsigned long flags; - int ret = 0; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); @@ -377,36 +304,26 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) return -ENOMEM; } - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - - tx_ctl = HTC_SKB_CB(skb); - - /* Mgmt/Beacon frames don't use the TX buffer pool */ - if ((tx_ctl->type == ATH9K_HTC_MGMT) || - (tx_ctl->type == ATH9K_HTC_BEACON)) { - ret = hif_usb_send_mgmt(hif_dev, skb); - } - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); + hif_dev->tx.tx_skb_cnt++; - if ((tx_ctl->type == ATH9K_HTC_NORMAL) || - (tx_ctl->type == ATH9K_HTC_AMPDU)) { - __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); - hif_dev->tx.tx_skb_cnt++; - } + /* Send normal frames immediately */ + if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) + __hif_usb_tx(hif_dev); /* Check if AMPDUs have to be sent immediately */ - if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && + if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && + (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && (hif_dev->tx.tx_skb_cnt < 2)) { __hif_usb_tx(hif_dev); } spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - return ret; + return 0; } -static void hif_usb_start(void *hif_handle) +static void hif_usb_start(void *hif_handle, u8 pipe_id) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; unsigned long flags; @@ -418,14 +335,14 @@ static void hif_usb_start(void *hif_handle) spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); } -static void hif_usb_stop(void *hif_handle) +static void hif_usb_stop(void *hif_handle, u8 pipe_id) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; unsigned long flags; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false); + ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue); hif_dev->tx.tx_skb_cnt = 0; hif_dev->tx.flags |= HIF_USB_TX_STOP; spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); @@ -435,18 +352,17 @@ static void hif_usb_stop(void *hif_handle) &hif_dev->tx.tx_pending, list) { usb_kill_urb(tx_buf->urb); } - - usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); } -static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) +static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, + struct ath9k_htc_tx_ctl *tx_ctl) { struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; int ret = 0; switch (pipe_id) { case USB_WLAN_TX_PIPE: - ret = hif_usb_send_tx(hif_dev, skb); + ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); break; case USB_REG_OUT_PIPE: ret = hif_usb_send_regout(hif_dev, skb); @@ -461,40 +377,6 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) return ret; } -static inline bool check_index(struct sk_buff *skb, u8 idx) -{ - struct ath9k_htc_tx_ctl *tx_ctl; - - tx_ctl = HTC_SKB_CB(skb); - - if ((tx_ctl->type == ATH9K_HTC_AMPDU) && - (tx_ctl->sta_idx == idx)) - return true; - - return false; -} - -static void hif_usb_sta_drain(void *hif_handle, u8 idx) -{ - struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; - struct sk_buff *skb, *tmp; - unsigned long flags; - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - - skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) { - if (check_index(skb, idx)) { - __skb_unlink(skb, &hif_dev->tx.tx_skb_queue); - ath9k_htc_txcompletion_cb(hif_dev->htc_handle, - skb, false); - hif_dev->tx.tx_skb_cnt--; - TX_STAT_INC(skb_failed); - } - } - - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -} - static struct ath9k_htc_hif hif_usb = { .transport = ATH9K_HIF_USB, .name = "ath9k_hif_usb", @@ -504,7 +386,6 @@ static struct ath9k_htc_hif hif_usb = { .start = hif_usb_start, .stop = hif_usb_stop, - .sta_drain = hif_usb_sta_drain, .send = hif_usb_send, }; @@ -686,9 +567,6 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) case -ESHUTDOWN: goto free; default: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - goto resubmit; } @@ -713,15 +591,23 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) USB_REG_IN_PIPE), nskb->data, MAX_REG_IN_BUF_SIZE, ath9k_hif_usb_reg_in_cb, nskb); + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + kfree_skb(nskb); + urb->context = NULL; + } + + return; } resubmit: - usb_anchor_urb(urb, &hif_dev->reg_in_submitted); + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - usb_unanchor_urb(urb); + if (ret) goto free; - } return; free: @@ -755,8 +641,6 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) kfree(tx_buf->buf); kfree(tx_buf); } - - usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); } static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) @@ -768,7 +652,6 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) INIT_LIST_HEAD(&hif_dev->tx.tx_pending); spin_lock_init(&hif_dev->tx.tx_lock); __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); - init_usb_anchor(&hif_dev->mgmt_submitted); for (i = 0; i < MAX_TX_URB_NUM; i++) { tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); @@ -865,67 +748,43 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) return ret; } -static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev) +static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) { - usb_kill_anchored_urbs(&hif_dev->reg_in_submitted); + if (hif_dev->reg_in_urb) { + usb_kill_urb(hif_dev->reg_in_urb); + if (hif_dev->reg_in_urb->context) + kfree_skb((void *)hif_dev->reg_in_urb->context); + usb_free_urb(hif_dev->reg_in_urb); + hif_dev->reg_in_urb = NULL; + } } -static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) { - struct urb *urb = NULL; - struct sk_buff *skb = NULL; - int i, ret; - - init_usb_anchor(&hif_dev->reg_in_submitted); - - for (i = 0; i < MAX_REG_IN_URB_NUM; i++) { - - /* Allocate URB */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) { - ret = -ENOMEM; - goto err_urb; - } - - /* Allocate buffer */ - skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); - if (!skb) { - ret = -ENOMEM; - goto err_skb; - } + struct sk_buff *skb; - usb_fill_bulk_urb(urb, hif_dev->udev, - usb_rcvbulkpipe(hif_dev->udev, - USB_REG_IN_PIPE), - skb->data, MAX_REG_IN_BUF_SIZE, - ath9k_hif_usb_reg_in_cb, skb); + hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (hif_dev->reg_in_urb == NULL) + return -ENOMEM; - /* Anchor URB */ - usb_anchor_urb(urb, &hif_dev->reg_in_submitted); + skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); + if (!skb) + goto err; - /* Submit URB */ - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret) { - usb_unanchor_urb(urb); - goto err_submit; - } + usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev, + usb_rcvbulkpipe(hif_dev->udev, + USB_REG_IN_PIPE), + skb->data, MAX_REG_IN_BUF_SIZE, + ath9k_hif_usb_reg_in_cb, skb); - /* - * Drop reference count. - * This ensures that the URB is freed when killing them. - */ - usb_free_urb(urb); - } + if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) + goto err; return 0; -err_submit: - kfree_skb(skb); -err_skb: - usb_free_urb(urb); -err_urb: - ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); - return ret; +err: + ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); + return -ENOMEM; } static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) @@ -942,7 +801,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) goto err_rx; /* Register Read */ - if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0) + if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) goto err_reg; return 0; @@ -957,7 +816,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) { usb_kill_anchored_urbs(&hif_dev->regout_submitted); - ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); + ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); ath9k_hif_usb_dealloc_tx_urbs(hif_dev); ath9k_hif_usb_dealloc_rx_urbs(hif_dev); } @@ -1167,7 +1026,10 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, /* Find out which firmware to load */ if (IS_AR7010_DEVICE(id->driver_info)) - hif_dev->fw_name = FIRMWARE_AR7010_1_1; + if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) + hif_dev->fw_name = FIRMWARE_AR7010_1_1; + else + hif_dev->fw_name = FIRMWARE_AR7010; else hif_dev->fw_name = FIRMWARE_AR9271; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.h b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.h index 2bdcdbc14b1e..7b9d863d4035 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -17,9 +17,6 @@ #ifndef HTC_USB_H #define HTC_USB_H -#define MAJOR_VERSION_REQ 1 -#define MINOR_VERSION_REQ 2 - #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) #define AR9271_FIRMWARE 0x501000 @@ -34,7 +31,7 @@ /* FIXME: Verify these numbers (with Windows) */ #define MAX_TX_URB_NUM 8 -#define MAX_TX_BUF_NUM 256 +#define MAX_TX_BUF_NUM 1024 #define MAX_TX_BUF_SIZE 32768 #define MAX_TX_AGGR_NUM 20 @@ -43,7 +40,7 @@ #define MAX_PKT_NUM_IN_TRANSFER 10 #define MAX_REG_OUT_URB_NUM 1 -#define MAX_REG_IN_URB_NUM 64 +#define MAX_REG_OUT_BUF_NUM 8 #define MAX_REG_IN_BUF_SIZE 64 @@ -93,10 +90,9 @@ struct hif_device_usb { const struct firmware *firmware; struct htc_target *htc_handle; struct hif_usb_tx tx; + struct urb *reg_in_urb; struct usb_anchor regout_submitted; struct usb_anchor rx_submitted; - struct usb_anchor reg_in_submitted; - struct usb_anchor mgmt_submitted; struct sk_buff *remain_skb; const char *fw_name; int rx_remain_len; diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc.h b/trunk/drivers/net/wireless/ath/ath9k/htc.h index 6bb71e311a4b..753a245c5ad1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc.h +++ b/trunk/drivers/net/wireless/ath/ath9k/htc.h @@ -66,13 +66,13 @@ enum htc_opmode { HTC_M_WDS = 2 }; -#define ATH9K_HTC_AMPDU 1 +#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) +#define ATH9K_HTC_AMPDU 1 #define ATH9K_HTC_NORMAL 2 -#define ATH9K_HTC_BEACON 3 -#define ATH9K_HTC_MGMT 4 #define ATH9K_HTC_TX_CTSONLY 0x1 #define ATH9K_HTC_TX_RTSCTS 0x2 +#define ATH9K_HTC_TX_USE_MIN_RATE 0x100 struct tx_frame_hdr { u8 data_type; @@ -82,8 +82,7 @@ struct tx_frame_hdr { __be32 flags; /* ATH9K_HTC_TX_* */ u8 key_type; u8 keyix; - u8 cookie; - u8 pad; + u8 reserved[26]; } __packed; struct tx_mgmt_hdr { @@ -93,34 +92,50 @@ struct tx_mgmt_hdr { u8 flags; u8 key_type; u8 keyix; - u8 cookie; - u8 pad; + u16 reserved; } __packed; struct tx_beacon_header { - u8 vif_index; u8 len_changed; + u8 vif_index; u16 rev; } __packed; -#define MAX_TX_AMPDU_SUBFRAMES_9271 17 -#define MAX_TX_AMPDU_SUBFRAMES_7010 22 +struct ath9k_htc_target_hw { + u32 flags; + u32 flags_ext; + u32 ampdu_limit; + u8 ampdu_subframes; + u8 tx_chainmask; + u8 tx_chainmask_legacy; + u8 rtscts_ratecode; + u8 protmode; +} __packed; struct ath9k_htc_cap_target { - __be32 ampdu_limit; + u32 flags; + u32 flags_ext; + u32 ampdu_limit; u8 ampdu_subframes; - u8 enable_coex; u8 tx_chainmask; - u8 pad; + u8 tx_chainmask_legacy; + u8 rtscts_ratecode; + u8 protmode; } __packed; struct ath9k_htc_target_vif { u8 index; - u8 opmode; + u8 des_bssid[ETH_ALEN]; + __be32 opmode; u8 myaddr[ETH_ALEN]; - u8 ath_cap; + u8 bssid[ETH_ALEN]; + u32 flags; + u32 flags_ext; + u16 ps_sta; __be16 rtsthreshold; - u8 pad; + u8 ath_cap; + u8 node; + s8 mcast_rate; } __packed; #define ATH_HTC_STA_AUTH 0x0001 @@ -128,16 +143,27 @@ struct ath9k_htc_target_vif { #define ATH_HTC_STA_ERP 0x0004 #define ATH_HTC_STA_HT 0x0008 +/* FIXME: UAPSD variables */ struct ath9k_htc_target_sta { + u16 associd; + u16 txpower; + u32 ucastkey; u8 macaddr[ETH_ALEN]; u8 bssid[ETH_ALEN]; u8 sta_index; u8 vif_index; - u8 is_vif_sta; + u8 vif_sta; __be16 flags; /* ATH_HTC_STA_* */ - __be16 htcap; - __be16 maxampdu; - u8 pad; + u16 htcap; + u8 valid; + u16 capinfo; + struct ath9k_htc_target_hw *hw; + struct ath9k_htc_target_vif *vif; + u16 txseqmgmt; + u8 is_vif_sta; + u16 maxampdu; + u16 iv16; + u32 iv32; } __packed; struct ath9k_htc_target_aggr { @@ -171,38 +197,12 @@ struct ath9k_htc_target_rate { struct ath9k_htc_rate rates; }; -struct ath9k_htc_target_rate_mask { - u8 vif_index; - u8 band; - __be32 mask; - u16 pad; -} __packed; - -struct ath9k_htc_target_int_stats { - __be32 rx; - __be32 rxorn; - __be32 rxeol; - __be32 txurn; - __be32 txto; - __be32 cst; -} __packed; - -struct ath9k_htc_target_tx_stats { - __be32 xretries; - __be32 fifoerr; - __be32 filtered; - __be32 timer_exp; - __be32 shortretries; - __be32 longretries; - __be32 qnull; - __be32 encap_fail; - __be32 nobuf; -} __packed; - -struct ath9k_htc_target_rx_stats { - __be32 nobuf; - __be32 host_send; - __be32 host_done; +struct ath9k_htc_target_stats { + __be32 tx_shortretry; + __be32 tx_longretry; + __be32 tx_xretries; + __be32 ht_txunaggr_xretry; + __be32 ht_tx_xretries; } __packed; #define ATH9K_HTC_MAX_VIF 2 @@ -244,8 +244,6 @@ struct ath9k_htc_vif { u8 index; u16 seq_no; bool beacon_configured; - int bslot; - __le64 tsfadjust; }; struct ath9k_vif_iter_data { @@ -284,65 +282,23 @@ struct ath9k_htc_rx { spinlock_t rxbuflock; }; -#define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ -#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */ -#define ATH9K_HTC_TX_RESERVE 10 -#define ATH9K_HTC_TX_TIMEOUT_COUNT 20 -#define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) - -#define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) -#define ATH9K_HTC_OP_TX_DRAIN BIT(1) - -struct ath9k_htc_tx { - u8 flags; - int queued_cnt; - struct sk_buff_head mgmt_ep_queue; - struct sk_buff_head cab_ep_queue; - struct sk_buff_head data_be_queue; - struct sk_buff_head data_bk_queue; - struct sk_buff_head data_vi_queue; - struct sk_buff_head data_vo_queue; - struct sk_buff_head tx_failed; - DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); - struct timer_list cleanup_timer; - spinlock_t tx_lock; -}; - struct ath9k_htc_tx_ctl { u8 type; /* ATH9K_HTC_* */ - u8 epid; - u8 txok; - u8 sta_idx; - unsigned long timestamp; }; -static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) > - IEEE80211_TX_INFO_DRIVER_DATA_SIZE); - return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data; -} - #ifdef CONFIG_ATH9K_HTC_DEBUGFS #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) -#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) -void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, - struct ath_htc_rx_status *rxs); - struct ath_tx_stats { u32 buf_queued; u32 buf_completed; u32 skb_queued; - u32 skb_success; - u32 skb_failed; - u32 cab_queued; + u32 skb_completed; + u32 skb_dropped; u32 queue_stats[WME_NUM_AC]; }; @@ -350,39 +306,29 @@ struct ath_rx_stats { u32 skb_allocated; u32 skb_completed; u32 skb_dropped; - u32 err_crc; - u32 err_decrypt_crc; - u32 err_mic; - u32 err_pre_delim; - u32 err_post_delim; - u32 err_decrypt_busy; - u32 err_phy; - u32 err_phy_stats[ATH9K_PHYERR_MAX]; }; struct ath9k_debug { struct dentry *debugfs_phy; + struct dentry *debugfs_tgt_stats; + struct dentry *debugfs_xmit; + struct dentry *debugfs_recv; struct ath_tx_stats tx_stats; struct ath_rx_stats rx_stats; + u32 txrate; }; #else #define TX_STAT_INC(c) do { } while (0) #define RX_STAT_INC(c) do { } while (0) -#define CAB_STAT_INC do { } while (0) #define TX_QSTAT_INC(c) do { } while (0) -static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, - struct ath_htc_rx_status *rxs) -{ -} - #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #define ATH_LED_PIN_DEF 1 -#define ATH_LED_PIN_9287 10 +#define ATH_LED_PIN_9287 8 #define ATH_LED_PIN_9271 15 #define ATH_LED_PIN_7010 12 #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ @@ -405,21 +351,10 @@ struct ath_led { int brightness; }; -#define BSTUCK_THRESHOLD 10 - -/* - * Adjust these when the max. no of beaconing interfaces is - * increased. - */ -#define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ -#define MIN_SWBA_RESPONSE 10 /* in TUs */ - struct htc_beacon_config { - struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; u16 beacon_interval; u16 dtim_period; u16 bmiss_timeout; - u32 bmiss_cnt; }; struct ath_btcoex { @@ -453,9 +388,6 @@ struct ath9k_htc_priv { struct htc_target *htc; struct wmi *wmi; - u16 fw_version_major; - u16 fw_version_minor; - enum htc_endpoint_id wmi_cmd_ep; enum htc_endpoint_id beacon_ep; enum htc_endpoint_id cab_ep; @@ -479,23 +411,27 @@ struct ath9k_htc_priv { u16 txpowlimit; u16 nvifs; u16 nstations; + u32 bmiss_cnt; bool rearm_ani; bool reconfig_beacon; - unsigned int rxfilter; struct ath9k_hw_cal_data caldata; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; spinlock_t beacon_lock; - struct htc_beacon_config cur_beacon_conf; - struct ath9k_htc_rx rx; - struct ath9k_htc_tx tx; + bool tx_queues_stop; + spinlock_t tx_lock; + struct ieee80211_vif *vif; + struct htc_beacon_config cur_beacon_conf; + unsigned int rxfilter; struct tasklet_struct swba_tasklet; struct tasklet_struct rx_tasklet; + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ath9k_htc_rx rx; + struct tasklet_struct tx_tasklet; + struct sk_buff_head tx_queue; struct delayed_work ani_work; - struct tasklet_struct tx_failed_tasklet; struct work_struct ps_work; struct work_struct fatal_work; @@ -534,18 +470,11 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) void ath9k_htc_reset(struct ath9k_htc_priv *priv); -void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif); -void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif); -void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif); void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif); void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); -void ath9k_htc_swba(struct ath9k_htc_priv *priv, - struct wmi_event_swba *swba); +void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); void ath9k_htc_rxep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id); @@ -554,8 +483,7 @@ void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok); -int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, - u8 enable_coex); +int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv); void ath9k_htc_station_work(struct work_struct *work); void ath9k_htc_aggr_work(struct work_struct *work); void ath9k_htc_ani_work(struct work_struct *work); @@ -563,23 +491,14 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv); void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); int ath9k_tx_init(struct ath9k_htc_priv *priv); -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, - struct sk_buff *skb, u8 slot, bool is_cab); +void ath9k_tx_tasklet(unsigned long data); +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); int get_hw_qnum(u16 queue, int *hwq_map); int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo); -void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); -void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); -int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); -void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); -void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); -void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); -void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv); -void ath9k_tx_failed_tasklet(unsigned long data); -void ath9k_htc_tx_cleanup_timer(unsigned long data); int ath9k_rx_init(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); @@ -609,9 +528,15 @@ void ath9k_htc_suspend(struct htc_target *htc_handle); int ath9k_htc_resume(struct htc_target *htc_handle); #endif #ifdef CONFIG_ATH9K_HTC_DEBUGFS +int ath9k_htc_debug_create_root(void); +void ath9k_htc_debug_remove_root(void); int ath9k_htc_init_debug(struct ath_hw *ah); +void ath9k_htc_exit_debug(struct ath_hw *ah); #else +static inline int ath9k_htc_debug_create_root(void) { return 0; }; +static inline void ath9k_htc_debug_remove_root(void) {}; static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; +static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {}; #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #endif /* HTC_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 0ded2c66d5ff..8d1d8792436d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -18,50 +18,6 @@ #define FUDGE 2 -void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) -{ - struct ath_hw *ah = priv->ah; - struct ath9k_tx_queue_info qi, qi_be; - - memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); - memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); - - ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); - - if (priv->ah->opmode == NL80211_IFTYPE_AP) { - qi.tqi_aifs = 1; - qi.tqi_cwmin = 0; - qi.tqi_cwmax = 0; - } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { - int qnum = priv->hwq_map[WME_AC_BE]; - - ath9k_hw_get_txq_props(ah, qnum, &qi_be); - - qi.tqi_aifs = qi_be.tqi_aifs; - - /* - * For WIFI Beacon Distribution - * Long slot time : 2x cwmin - * Short slot time : 4x cwmin - */ - if (ah->slottime == ATH9K_SLOT_TIME_20) - qi.tqi_cwmin = 2*qi_be.tqi_cwmin; - else - qi.tqi_cwmin = 4*qi_be.tqi_cwmin; - - qi.tqi_cwmax = qi_be.tqi_cwmax; - - } - - if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { - ath_err(ath9k_hw_common(ah), - "Unable to update beacon queue %u!\n", priv->beaconq); - } else { - ath9k_hw_resettxqueue(ah, priv->beaconq); - } -} - - static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, struct htc_beacon_config *bss_conf) { @@ -74,7 +30,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, __be32 htc_imask = 0; u64 tsf; int num_beacons, offset, dtim_dec_count, cfp_dec_count; - int ret __attribute__ ((unused)); + int ret; u8 cmd_rsp; memset(&bs, 0, sizeof(bs)); @@ -190,7 +146,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, enum ath9k_int imask = 0; u32 nexttbtt, intval, tsftu; __be32 htc_imask = 0; - int ret __attribute__ ((unused)); + int ret; u8 cmd_rsp; u64 tsf; @@ -198,17 +154,8 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, intval /= ATH9K_HTC_MAX_BCN_VIF; nexttbtt = intval; - /* - * To reduce beacon misses under heavy TX load, - * set the beacon response time to a larger value. - */ - if (intval > DEFAULT_SWBA_RESPONSE) - priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; - else - priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; - if (priv->op_flags & OP_TSF_RESET) { - ath9k_hw_reset_tsf(priv->ah); + intval |= ATH9K_BEACON_RESET_TSF; priv->op_flags &= ~OP_TSF_RESET; } else { /* @@ -221,20 +168,18 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, } while (nexttbtt < tsftu); } + intval |= ATH9K_BEACON_ENA; + if (priv->op_flags & OP_ENABLE_BEACON) imask |= ATH9K_INT_SWBA; ath_dbg(common, ATH_DBG_CONFIG, - "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " - "imask: 0x%x\n", - bss_conf->beacon_interval, nexttbtt, - priv->ah->config.sw_beacon_response_time, imask); - - ath9k_htc_beaconq_config(priv); + "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n", + bss_conf->beacon_interval, nexttbtt, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); - ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); - priv->cur_beacon_conf.bmiss_cnt = 0; + ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); + priv->bmiss_cnt = 0; htc_imask = cpu_to_be32(imask); WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); } @@ -246,7 +191,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, enum ath9k_int imask = 0; u32 nexttbtt, intval, tsftu; __be32 htc_imask = 0; - int ret __attribute__ ((unused)); + int ret; u8 cmd_rsp; u64 tsf; @@ -262,26 +207,17 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, nexttbtt += intval; } while (nexttbtt < tsftu); - /* - * Only one IBSS interfce is allowed. - */ - if (intval > DEFAULT_SWBA_RESPONSE) - priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; - else - priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; - + intval |= ATH9K_BEACON_ENA; if (priv->op_flags & OP_ENABLE_BEACON) imask |= ATH9K_INT_SWBA; ath_dbg(common, ATH_DBG_CONFIG, - "IBSS Beacon config, intval: %d, nexttbtt: %u, " - "resp_time: %d, imask: 0x%x\n", - bss_conf->beacon_interval, nexttbtt, - priv->ah->config.sw_beacon_response_time, imask); + "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", + bss_conf->beacon_interval, nexttbtt, imask); WMI_CMD(WMI_DISABLE_INTR_CMDID); - ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); - priv->cur_beacon_conf.bmiss_cnt = 0; + ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); + priv->bmiss_cnt = 0; htc_imask = cpu_to_be32(imask); WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); } @@ -292,81 +228,25 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, dev_kfree_skb_any(skb); } -static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, - int slot) +void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) { - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ieee80211_vif *vif; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - int padpos, padsize, ret, tx_slot; - - spin_lock_bh(&priv->beacon_lock); - - vif = priv->cur_beacon_conf.bslot[slot]; - - skb = ieee80211_get_buffered_bc(priv->hw, vif); - - while(skb) { - hdr = (struct ieee80211_hdr *) skb->data; - - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len > padpos) { - if (skb_headroom(skb) < padsize) { - dev_kfree_skb_any(skb); - goto next; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, padpos); - } - - tx_slot = ath9k_htc_tx_get_slot(priv); - if (tx_slot < 0) { - ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); - dev_kfree_skb_any(skb); - goto next; - } - - ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); - if (ret != 0) { - ath9k_htc_tx_clear_slot(priv, tx_slot); - dev_kfree_skb_any(skb); - - ath_dbg(common, ATH_DBG_XMIT, - "Failed to send CAB frame\n"); - } else { - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.queued_cnt++; - spin_unlock_bh(&priv->tx.tx_lock); - } - next: - skb = ieee80211_get_buffered_bc(priv->hw, vif); - } - - spin_unlock_bh(&priv->beacon_lock); -} - -static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, - int slot) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ieee80211_vif *vif; - struct ath9k_htc_vif *avp; + struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; struct tx_beacon_header beacon_hdr; - struct ath9k_htc_tx_ctl *tx_ctl; + struct ath9k_htc_tx_ctl tx_ctl; struct ieee80211_tx_info *info; - struct ieee80211_mgmt *mgmt; struct sk_buff *beacon; u8 *tx_fhdr; - int ret; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); + memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); - spin_lock_bh(&priv->beacon_lock); + /* FIXME: Handle BMISS */ + if (beacon_pending != 0) { + priv->bmiss_cnt++; + return; + } - vif = priv->cur_beacon_conf.bslot[slot]; - avp = (struct ath9k_htc_vif *)vif->drv_priv; + spin_lock_bh(&priv->beacon_lock); if (unlikely(priv->op_flags & OP_SCANNING)) { spin_unlock_bh(&priv->beacon_lock); @@ -374,19 +254,12 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, } /* Get a new beacon */ - beacon = ieee80211_beacon_get(priv->hw, vif); + beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; } - /* - * Update the TSF adjust value here, the HW will - * add this value for every beacon. - */ - mgmt = (struct ieee80211_mgmt *)beacon->data; - mgmt->u.beacon.timestamp = avp->tsfadjust; - info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = @@ -396,149 +269,45 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); } - tx_ctl = HTC_SKB_CB(beacon); - memset(tx_ctl, 0, sizeof(*tx_ctl)); - - tx_ctl->type = ATH9K_HTC_BEACON; - tx_ctl->epid = priv->beacon_ep; - + tx_ctl.type = ATH9K_HTC_NORMAL; beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); - ret = htc_send(priv->htc, beacon); - if (ret != 0) { - if (ret == -ENOMEM) { - ath_dbg(common, ATH_DBG_BSTUCK, - "Failed to send beacon, no free TX buffer\n"); - } - dev_kfree_skb_any(beacon); - } - - spin_unlock_bh(&priv->beacon_lock); -} - -static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, - struct wmi_event_swba *swba) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - u64 tsf; - u32 tsftu; - u16 intval; - int slot; - - intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; - - tsf = be64_to_cpu(swba->tsf); - tsftu = TSF_TO_TU(tsf >> 32, tsf); - slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; - slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; - - ath_dbg(common, ATH_DBG_BEACON, - "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", - slot, tsf, tsftu, intval); - - return slot; -} - -void ath9k_htc_swba(struct ath9k_htc_priv *priv, - struct wmi_event_swba *swba) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - int slot; - - if (swba->beacon_pending != 0) { - priv->cur_beacon_conf.bmiss_cnt++; - if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { - ath_dbg(common, ATH_DBG_BSTUCK, - "Beacon stuck, HW reset\n"); - ieee80211_queue_work(priv->hw, - &priv->fatal_work); - } - return; - } - - if (priv->cur_beacon_conf.bmiss_cnt) { - ath_dbg(common, ATH_DBG_BSTUCK, - "Resuming beacon xmit after %u misses\n", - priv->cur_beacon_conf.bmiss_cnt); - priv->cur_beacon_conf.bmiss_cnt = 0; - } + htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); - slot = ath9k_htc_choose_bslot(priv, swba); - spin_lock_bh(&priv->beacon_lock); - if (priv->cur_beacon_conf.bslot[slot] == NULL) { - spin_unlock_bh(&priv->beacon_lock); - return; - } spin_unlock_bh(&priv->beacon_lock); - - ath9k_htc_send_buffered(priv, slot); - ath9k_htc_send_beacon(priv, slot); } -void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; - int i = 0; - - spin_lock_bh(&priv->beacon_lock); - for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { - if (priv->cur_beacon_conf.bslot[i] == NULL) { - avp->bslot = i; - break; - } - } - - priv->cur_beacon_conf.bslot[avp->bslot] = vif; - spin_unlock_bh(&priv->beacon_lock); - - ath_dbg(common, ATH_DBG_CONFIG, - "Added interface at beacon slot: %d\n", avp->bslot); -} - -void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif) +/* Currently, only for IBSS */ +void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) { - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; - - spin_lock_bh(&priv->beacon_lock); - priv->cur_beacon_conf.bslot[avp->bslot] = NULL; - spin_unlock_bh(&priv->beacon_lock); - - ath_dbg(common, ATH_DBG_CONFIG, - "Removed interface at beacon slot: %d\n", avp->bslot); -} + struct ath_hw *ah = priv->ah; + struct ath9k_tx_queue_info qi, qi_be; + int qnum = priv->hwq_map[WME_AC_BE]; -/* - * Calculate the TSF adjustment value for all slots - * other than zero. - */ -void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; - struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; - u64 tsfadjust; + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); - if (avp->bslot == 0) - return; + ath9k_hw_get_txq_props(ah, qnum, &qi_be); - /* - * The beacon interval cannot be different for multi-AP mode, - * and we reach here only for VIF slots greater than zero, - * so beacon_interval is guaranteed to be set in cur_conf. + qi.tqi_aifs = qi_be.tqi_aifs; + /* For WIFI Beacon Distribution + * Long slot time : 2x cwmin + * Short slot time : 4x cwmin */ - tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; - avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); + if (ah->slottime == ATH9K_SLOT_TIME_20) + qi.tqi_cwmin = 2*qi_be.tqi_cwmin; + else + qi.tqi_cwmin = 4*qi_be.tqi_cwmin; + qi.tqi_cwmax = qi_be.tqi_cwmax; - ath_dbg(common, ATH_DBG_CONFIG, - "tsfadjust is: %llu for bslot: %d\n", - (unsigned long long)tsfadjust, avp->bslot); + if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { + ath_err(ath9k_hw_common(ah), + "Unable to update beacon queue %u!\n", qnum); + } else { + ath9k_hw_resettxqueue(ah, priv->beaconq); + } } static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c deleted file mode 100644 index 894e5ef3f8d1..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (c) 2010-2011 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "htc.h" - -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - struct ath9k_htc_target_int_stats cmd_rsp; - char buf[512]; - unsigned int len = 0; - int ret = 0; - - memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - - ath9k_htc_ps_wakeup(priv); - - WMI_CMD(WMI_INT_STATS_CMDID); - if (ret) { - ath9k_htc_ps_restore(priv); - return -EINVAL; - } - - ath9k_htc_ps_restore(priv); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "RX", - be32_to_cpu(cmd_rsp.rx)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "RXORN", - be32_to_cpu(cmd_rsp.rxorn)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "RXEOL", - be32_to_cpu(cmd_rsp.rxeol)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "TXURN", - be32_to_cpu(cmd_rsp.txurn)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "TXTO", - be32_to_cpu(cmd_rsp.txto)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "CST", - be32_to_cpu(cmd_rsp.cst)); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_tgt_int_stats = { - .read = read_file_tgt_int_stats, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - struct ath9k_htc_target_tx_stats cmd_rsp; - char buf[512]; - unsigned int len = 0; - int ret = 0; - - memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - - ath9k_htc_ps_wakeup(priv); - - WMI_CMD(WMI_TX_STATS_CMDID); - if (ret) { - ath9k_htc_ps_restore(priv); - return -EINVAL; - } - - ath9k_htc_ps_restore(priv); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Xretries", - be32_to_cpu(cmd_rsp.xretries)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "FifoErr", - be32_to_cpu(cmd_rsp.fifoerr)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Filtered", - be32_to_cpu(cmd_rsp.filtered)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "TimerExp", - be32_to_cpu(cmd_rsp.timer_exp)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "ShortRetries", - be32_to_cpu(cmd_rsp.shortretries)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "LongRetries", - be32_to_cpu(cmd_rsp.longretries)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "QueueNull", - be32_to_cpu(cmd_rsp.qnull)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "EncapFail", - be32_to_cpu(cmd_rsp.encap_fail)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "NoBuf", - be32_to_cpu(cmd_rsp.nobuf)); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_tgt_tx_stats = { - .read = read_file_tgt_tx_stats, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - struct ath9k_htc_target_rx_stats cmd_rsp; - char buf[512]; - unsigned int len = 0; - int ret = 0; - - memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - - ath9k_htc_ps_wakeup(priv); - - WMI_CMD(WMI_RX_STATS_CMDID); - if (ret) { - ath9k_htc_ps_restore(priv); - return -EINVAL; - } - - ath9k_htc_ps_restore(priv); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "NoBuf", - be32_to_cpu(cmd_rsp.nobuf)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "HostSend", - be32_to_cpu(cmd_rsp.host_send)); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "HostDone", - be32_to_cpu(cmd_rsp.host_done)); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_tgt_rx_stats = { - .read = read_file_tgt_rx_stats, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_xmit(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Buffers queued", - priv->debug.tx_stats.buf_queued); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "Buffers completed", - priv->debug.tx_stats.buf_completed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs queued", - priv->debug.tx_stats.skb_queued); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs success", - priv->debug.tx_stats.skb_success); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "SKBs failed", - priv->debug.tx_stats.skb_failed); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "CAB queued", - priv->debug.tx_stats.cab_queued); - - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "BE queued", - priv->debug.tx_stats.queue_stats[WME_AC_BE]); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "BK queued", - priv->debug.tx_stats.queue_stats[WME_AC_BK]); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "VI queued", - priv->debug.tx_stats.queue_stats[WME_AC_VI]); - len += snprintf(buf + len, sizeof(buf) - len, - "%20s : %10u\n", "VO queued", - priv->debug.tx_stats.queue_stats[WME_AC_VO]); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_xmit = { - .read = read_file_xmit, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, - struct ath_htc_rx_status *rxs) -{ -#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ - - if (rxs->rs_status & ATH9K_RXERR_CRC) - priv->debug.rx_stats.err_crc++; - if (rxs->rs_status & ATH9K_RXERR_DECRYPT) - priv->debug.rx_stats.err_decrypt_crc++; - if (rxs->rs_status & ATH9K_RXERR_MIC) - priv->debug.rx_stats.err_mic++; - if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) - priv->debug.rx_stats.err_pre_delim++; - if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) - priv->debug.rx_stats.err_post_delim++; - if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) - priv->debug.rx_stats.err_decrypt_busy++; - - if (rxs->rs_status & ATH9K_RXERR_PHY) { - priv->debug.rx_stats.err_phy++; - if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) - RX_PHY_ERR_INC(rxs->rs_phyerr); - } - -#undef RX_PHY_ERR_INC -} - -static ssize_t read_file_recv(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ -#define PHY_ERR(s, p) \ - len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \ - priv->debug.rx_stats.err_phy_stats[p]); - - struct ath9k_htc_priv *priv = file->private_data; - char *buf; - unsigned int len = 0, size = 1500; - ssize_t retval = 0; - - buf = kzalloc(size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "SKBs allocated", - priv->debug.rx_stats.skb_allocated); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "SKBs completed", - priv->debug.rx_stats.skb_completed); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "SKBs Dropped", - priv->debug.rx_stats.skb_dropped); - - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "CRC ERR", - priv->debug.rx_stats.err_crc); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "DECRYPT CRC ERR", - priv->debug.rx_stats.err_decrypt_crc); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "MIC ERR", - priv->debug.rx_stats.err_mic); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "PRE-DELIM CRC ERR", - priv->debug.rx_stats.err_pre_delim); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "POST-DELIM CRC ERR", - priv->debug.rx_stats.err_post_delim); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "DECRYPT BUSY ERR", - priv->debug.rx_stats.err_decrypt_busy); - len += snprintf(buf + len, size - len, - "%20s : %10u\n", "TOTAL PHY ERR", - priv->debug.rx_stats.err_phy); - - - PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); - PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); - PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); - PHY_ERR("RATE", ATH9K_PHYERR_RATE); - PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); - PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); - PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); - PHY_ERR("TOR", ATH9K_PHYERR_TOR); - PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); - PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); - PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); - PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); - PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); - PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); - PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); - PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); - PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); - PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); - PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); - PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); - PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); - PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); - PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); - PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); - PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); - PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); - - if (len > size) - len = size; - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - - return retval; - -#undef PHY_ERR -} - -static const struct file_operations fops_recv = { - .read = read_file_recv, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_slot(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - char buf[512]; - unsigned int len = 0; - - spin_lock_bh(&priv->tx.tx_lock); - - len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); - - len += bitmap_scnprintf(buf + len, sizeof(buf) - len, - priv->tx.tx_slot, MAX_TX_BUF_NUM); - - len += snprintf(buf + len, sizeof(buf) - len, "\n"); - - len += snprintf(buf + len, sizeof(buf) - len, - "Used slots : %d\n", - bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); - - spin_unlock_bh(&priv->tx.tx_lock); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_slot = { - .read = read_file_slot, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_queue(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); - - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Failed queue", skb_queue_len(&priv->tx.tx_failed)); - - spin_lock_bh(&priv->tx.tx_lock); - len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", - "Queued count", priv->tx.queued_cnt); - spin_unlock_bh(&priv->tx.tx_lock); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); - -} - -static const struct file_operations fops_queue = { - .read = read_file_queue, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_debug(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - struct ath_common *common = ath9k_hw_common(priv->ah); - char buf[32]; - unsigned int len; - - len = sprintf(buf, "0x%08x\n", common->debug_mask); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_debug(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath9k_htc_priv *priv = file->private_data; - struct ath_common *common = ath9k_hw_common(priv->ah); - unsigned long mask; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (strict_strtoul(buf, 0, &mask)) - return -EINVAL; - - common->debug_mask = mask; - return count; -} - -static const struct file_operations fops_debug = { - .read = read_file_debug, - .write = write_file_debug, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -int ath9k_htc_init_debug(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - - priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, - priv->hw->wiphy->debugfsdir); - if (!priv->debug.debugfs_phy) - return -ENOMEM; - - debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_tgt_int_stats); - debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_tgt_tx_stats); - debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_tgt_rx_stats); - debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_xmit); - debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_recv); - debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_slot); - debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, - priv, &fops_queue); - debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, - priv, &fops_debug); - - return 0; -} diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 26ede1daa304..7e630a81b453 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -65,19 +65,17 @@ static void ath_btcoex_period_work(struct work_struct *work) u32 timer_period; bool is_btscan; int ret; + u8 cmd_rsp, aggr; ath_detect_bt_priority(priv); is_btscan = !!(priv->op_flags & OP_BT_SCAN); - ret = ath9k_htc_update_cap_target(priv, - !!(priv->op_flags & OP_BT_PRIORITY_DETECTED)); - if (ret) { - ath_err(common, "Unable to set BTCOEX parameters\n"); - return; - } + aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; - ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : + WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); + + ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type); timer_period = is_btscan ? btcoex->btscan_no_stomp : @@ -105,9 +103,9 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work) "time slice work for bt and wlan\n"); if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) - ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); + ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); } void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) @@ -400,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw) /* Start TX */ htc_start(priv->htc); - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; - spin_unlock_bh(&priv->tx.tx_lock); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); ieee80211_wake_queues(hw); WMI_CMD(WMI_ENABLE_INTR_CMDID); @@ -431,15 +429,13 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw) /* Stop TX */ ieee80211_stop_queues(hw); - ath9k_htc_tx_drain(priv); + htc_stop(priv->htc); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); + skb_queue_purge(&priv->tx_queue); /* Stop RX */ WMI_CMD(WMI_STOP_RECV_CMDID); - /* Clear the WMI event queue */ - ath9k_wmi_event_drain(priv); - /* * The MIB counters have to be disabled here, * since the target doesn't do it. diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d2dd5a63e10a..fc67c937e172 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -140,6 +140,7 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) { + ath9k_htc_exit_debug(priv->ah); ath9k_hw_deinit(priv->ah); kfree(priv->ah); priv->ah = NULL; @@ -243,7 +244,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, */ if (IS_AR7010_DEVICE(drv_info)) - priv->htc->credits = 48; + priv->htc->credits = 45; else priv->htc->credits = 33; @@ -429,16 +430,13 @@ static void ath9k_regwrite_flush(void *hw_priv) mutex_unlock(&priv->wmi->multi_write_mutex); } -static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) -{ - u32 val; - - val = ath9k_regread(hw_priv, reg_offset); - val &= ~clr; - val |= set; - ath9k_regwrite(hw_priv, val, reg_offset); - return val; -} +static const struct ath_ops ath9k_common_ops = { + .read = ath9k_regread, + .multi_read = ath9k_multi_regread, + .write = ath9k_regwrite, + .enable_write_buffer = ath9k_enable_regwrite_buffer, + .write_flush = ath9k_regwrite_flush, +}; static void ath_usb_read_cachesize(struct ath_common *common, int *csz) { @@ -563,7 +561,13 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) int i = 0; /* Get the hardware key cache size. */ - common->keymax = AR_KEYTABLE_SIZE; + common->keymax = priv->ah->caps.keycache_size; + if (common->keymax > ATH_KEYMAX) { + ath_dbg(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); + common->keymax = ATH_KEYMAX; + } if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; @@ -642,7 +646,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, { struct ath_hw *ah = NULL; struct ath_common *common; - int i, ret = 0, csz = 0; + int ret = 0, csz = 0; priv->op_flags |= OP_INVALID; @@ -654,35 +658,30 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, ah->hw_version.subsysid = 0; /* FIXME */ ah->hw_version.usbdev = drv_info; ah->ah_flags |= AH_USE_EEPROM; - ah->reg_ops.read = ath9k_regread; - ah->reg_ops.multi_read = ath9k_multi_regread; - ah->reg_ops.write = ath9k_regwrite; - ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; - ah->reg_ops.write_flush = ath9k_regwrite_flush; - ah->reg_ops.rmw = ath9k_reg_rmw; priv->ah = ah; common = ath9k_hw_common(ah); - common->ops = &ah->reg_ops; + common->ops = &ath9k_common_ops; common->bus_ops = &ath9k_usb_bus_ops; common->ah = ah; common->hw = priv->hw; common->priv = priv; common->debug_mask = ath9k_debug; + spin_lock_init(&priv->wmi->wmi_lock); spin_lock_init(&priv->beacon_lock); - spin_lock_init(&priv->tx.tx_lock); + spin_lock_init(&priv->tx_lock); mutex_init(&priv->mutex); mutex_init(&priv->htc_pm_lock); + tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet, + (unsigned long)priv); tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, (unsigned long)priv); - tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet, + tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); INIT_WORK(&priv->ps_work, ath9k_ps_work); INIT_WORK(&priv->fatal_work, ath9k_fatal_work); - setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer, - (unsigned long)priv); /* * Cache line size is used to size and align various @@ -699,13 +698,16 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, goto err_hw; } + ret = ath9k_htc_init_debug(ah); + if (ret) { + ath_err(common, "Unable to create debugfs files\n"); + goto err_debug; + } + ret = ath9k_init_queues(priv); if (ret) goto err_queues; - for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) - priv->cur_beacon_conf.bslot[i] = NULL; - ath9k_init_crypto(priv); ath9k_init_channels_rates(priv); ath9k_init_misc(priv); @@ -718,6 +720,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, return 0; err_queues: + ath9k_htc_exit_debug(ah); +err_debug: ath9k_hw_deinit(ah); err_hw: @@ -738,27 +742,17 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; + IEEE80211_HW_PS_NULLFUNC_STACK; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT); + BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->queues = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 10; - - if (AR_SREV_9271(priv->ah)) - hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271; - else - hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010; - hw->vif_data_size = sizeof(struct ath9k_htc_vif); hw->sta_data_size = sizeof(struct ath9k_htc_sta); @@ -785,43 +779,6 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } -static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) -{ - struct ieee80211_hw *hw = priv->hw; - struct wmi_fw_version cmd_rsp; - int ret; - - memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - - WMI_CMD(WMI_GET_FW_VERSION); - if (ret) - return -EINVAL; - - priv->fw_version_major = be16_to_cpu(cmd_rsp.major); - priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor); - - snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d", - priv->fw_version_major, - priv->fw_version_minor); - - dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n", - priv->fw_version_major, - priv->fw_version_minor); - - /* - * Check if the available FW matches the driver's - * required version. - */ - if (priv->fw_version_major != MAJOR_VERSION_REQ || - priv->fw_version_minor != MINOR_VERSION_REQ) { - dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n", - MAJOR_VERSION_REQ, MINOR_VERSION_REQ); - return -EINVAL; - } - - return 0; -} - static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid, char *product, u32 drv_info) { @@ -841,10 +798,6 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, common = ath9k_hw_common(ah); ath9k_set_hw_capab(priv, hw); - error = ath9k_init_firmware_version(priv); - if (error != 0) - goto err_fw; - /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, priv->hw->wiphy, ath9k_reg_notifier); @@ -875,12 +828,6 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, goto err_world; } - error = ath9k_htc_init_debug(priv->ah); - if (error) { - ath_err(common, "Unable to create debugfs files\n"); - goto err_world; - } - ath_dbg(common, ATH_DBG_CONFIG, "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " "BE:%d, BK:%d, VI:%d, VO:%d\n", @@ -911,8 +858,6 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, err_tx: /* Nothing */ err_regd: - /* Nothing */ -err_fw: ath9k_deinit_priv(priv); err_init: return error; @@ -1001,20 +946,38 @@ int ath9k_htc_resume(struct htc_target *htc_handle) static int __init ath9k_htc_init(void) { - if (ath9k_hif_usb_init() < 0) { + int error; + + error = ath9k_htc_debug_create_root(); + if (error < 0) { + printk(KERN_ERR + "ath9k_htc: Unable to create debugfs root: %d\n", + error); + goto err_dbg; + } + + error = ath9k_hif_usb_init(); + if (error < 0) { printk(KERN_ERR "ath9k_htc: No USB devices found," " driver not installed.\n"); - return -ENODEV; + error = -ENODEV; + goto err_usb; } return 0; + +err_usb: + ath9k_htc_debug_remove_root(); +err_dbg: + return error; } module_init(ath9k_htc_init); static void __exit ath9k_htc_exit(void) { ath9k_hif_usb_exit(); + ath9k_htc_debug_remove_root(); printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); } module_exit(ath9k_htc_exit); diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e9746e8ff8dd..db8c0c044e9e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -16,6 +16,10 @@ #include "htc.h" +#ifdef CONFIG_ATH9K_HTC_DEBUGFS +static struct dentry *ath9k_debugfs_root; +#endif + /*************/ /* Utilities */ /*************/ @@ -193,16 +197,11 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) ath9k_htc_stop_ani(priv); ieee80211_stop_queues(priv->hw); - - del_timer_sync(&priv->tx.cleanup_timer); - ath9k_htc_tx_drain(priv); - + htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - ath9k_wmi_event_drain(priv); - caldata = &priv->caldata; ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); if (ret) { @@ -226,9 +225,6 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) ath9k_htc_vif_reconfig(priv); ieee80211_wake_queues(priv->hw); - mod_timer(&priv->tx.cleanup_timer, - jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); - ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); } @@ -254,16 +250,11 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); ath9k_htc_ps_wakeup(priv); - - del_timer_sync(&priv->tx.cleanup_timer); - ath9k_htc_tx_drain(priv); - + htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - ath9k_wmi_event_drain(priv); - ath_dbg(common, ATH_DBG_CONFIG, "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", priv->ah->curchan->channel, @@ -272,7 +263,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, if (!fastcc) caldata = &priv->caldata; - ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { ath_err(common, @@ -306,9 +296,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) ath9k_htc_vif_reconfig(priv); - mod_timer(&priv->tx.cleanup_timer, - jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); - err: ath9k_htc_ps_restore(priv); return ret; @@ -332,11 +319,6 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); hvif.index = priv->mon_vif_idx; WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); - if (ret) { - ath_err(common, "Unable to remove monitor interface at idx: %d\n", - priv->mon_vif_idx); - } - priv->nvifs--; priv->vif_slot &= ~(1 << priv->mon_vif_idx); } @@ -367,7 +349,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); - hvif.opmode = HTC_M_MONITOR; + hvif.opmode = cpu_to_be32(HTC_M_MONITOR); hvif.index = ffz(priv->vif_slot); WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); @@ -400,7 +382,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) tsta.is_vif_sta = 1; tsta.sta_index = sta_idx; tsta.vif_index = hvif.index; - tsta.maxampdu = cpu_to_be16(0xffff); + tsta.maxampdu = 0xffff; WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); if (ret) { @@ -467,7 +449,6 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, struct ath9k_htc_sta *ista; int ret, sta_idx; u8 cmd_rsp; - u16 maxampdu; if (priv->nstations >= ATH9K_HTC_MAX_STA) return -ENOBUFS; @@ -482,7 +463,9 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, ista = (struct ath9k_htc_sta *) sta->drv_priv; memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); + tsta.associd = common->curaid; tsta.is_vif_sta = 0; + tsta.valid = true; ista->index = sta_idx; } else { memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); @@ -491,15 +474,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, tsta.sta_index = sta_idx; tsta.vif_index = avp->index; - - if (!sta) { - tsta.maxampdu = cpu_to_be16(0xffff); - } else { - maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + - sta->ht_cap.ampdu_factor); - tsta.maxampdu = cpu_to_be16(maxampdu); - } - + tsta.maxampdu = 0xffff; if (sta && sta->ht_cap.ht_supported) tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); @@ -572,8 +547,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, return 0; } -int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, - u8 enable_coex) +int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) { struct ath9k_htc_cap_target tcap; int ret; @@ -581,9 +555,13 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); - tcap.ampdu_limit = cpu_to_be32(0xffff); - tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; - tcap.enable_coex = enable_coex; + /* FIXME: Values are hardcoded */ + tcap.flags = 0x240c40; + tcap.flags_ext = 0x80601000; + tcap.ampdu_limit = 0xffff0000; + tcap.ampdu_subframes = 20; + tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; + tcap.protmode = 1; tcap.tx_chainmask = priv->ah->caps.tx_chainmask; WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); @@ -731,13 +709,218 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, (aggr.aggr_enable) ? "Starting" : "Stopping", sta->addr, tid); - spin_lock_bh(&priv->tx.tx_lock); + spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; - spin_unlock_bh(&priv->tx.tx_lock); + spin_unlock_bh(&priv->tx_lock); return ret; } +/*********/ +/* DEBUG */ +/*********/ + +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + +static int ath9k_debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + struct ath9k_htc_target_stats cmd_rsp; + char buf[512]; + unsigned int len = 0; + int ret = 0; + + memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + + WMI_CMD(WMI_TGT_STATS_CMDID); + if (ret) + return -EINVAL; + + + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Short Retries", + be32_to_cpu(cmd_rsp.tx_shortretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Long Retries", + be32_to_cpu(cmd_rsp.tx_longretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Xretries", + be32_to_cpu(cmd_rsp.tx_xretries)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Unaggr. Xretries", + be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Xretries (HT)", + be32_to_cpu(cmd_rsp.ht_tx_xretries)); + len += snprintf(buf + len, sizeof(buf) - len, + "%19s : %10u\n", "TX Rate", priv->debug.txrate); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_stats = { + .read = read_file_tgt_stats, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_xmit(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Buffers queued", + priv->debug.tx_stats.buf_queued); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "Buffers completed", + priv->debug.tx_stats.buf_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs queued", + priv->debug.tx_stats.skb_queued); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs completed", + priv->debug.tx_stats.skb_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs dropped", + priv->debug.tx_stats.skb_dropped); + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "BE queued", + priv->debug.tx_stats.queue_stats[WME_AC_BE]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "BK queued", + priv->debug.tx_stats.queue_stats[WME_AC_BK]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "VI queued", + priv->debug.tx_stats.queue_stats[WME_AC_VI]); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "VO queued", + priv->debug.tx_stats.queue_stats[WME_AC_VO]); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_xmit = { + .read = read_file_xmit, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_recv(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath9k_htc_priv *priv = file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs allocated", + priv->debug.rx_stats.skb_allocated); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs completed", + priv->debug.rx_stats.skb_completed); + len += snprintf(buf + len, sizeof(buf) - len, + "%20s : %10u\n", "SKBs Dropped", + priv->debug.rx_stats.skb_dropped); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_recv = { + .read = read_file_recv, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +int ath9k_htc_init_debug(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + if (!ath9k_debugfs_root) + return -ENOENT; + + priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), + ath9k_debugfs_root); + if (!priv->debug.debugfs_phy) + goto err; + + priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_tgt_stats); + if (!priv->debug.debugfs_tgt_stats) + goto err; + + + priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_xmit); + if (!priv->debug.debugfs_xmit) + goto err; + + priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, + priv->debug.debugfs_phy, + priv, &fops_recv); + if (!priv->debug.debugfs_recv) + goto err; + + return 0; + +err: + ath9k_htc_exit_debug(ah); + return -ENOMEM; +} + +void ath9k_htc_exit_debug(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + + debugfs_remove(priv->debug.debugfs_recv); + debugfs_remove(priv->debug.debugfs_xmit); + debugfs_remove(priv->debug.debugfs_tgt_stats); + debugfs_remove(priv->debug.debugfs_phy); +} + +int ath9k_htc_debug_create_root(void) +{ + ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!ath9k_debugfs_root) + return -ENOENT; + + return 0; +} + +void ath9k_htc_debug_remove_root(void) +{ + debugfs_remove(ath9k_debugfs_root); + ath9k_debugfs_root = NULL; +} + +#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ + /*******/ /* ANI */ /*******/ @@ -857,8 +1040,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - int padpos, padsize, ret, slot; + int padpos, padsize, ret; hdr = (struct ieee80211_hdr *) skb->data; @@ -866,32 +1048,30 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) padpos = ath9k_cmn_padpos(hdr->frame_control); padsize = padpos & 3; if (padsize && skb->len > padpos) { - if (skb_headroom(skb) < padsize) { - ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n"); + if (skb_headroom(skb) < padsize) goto fail_tx; - } skb_push(skb, padsize); memmove(skb->data, skb->data + padsize, padpos); } - slot = ath9k_htc_tx_get_slot(priv); - if (slot < 0) { - ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n"); - goto fail_tx; - } - - ret = ath9k_htc_tx_start(priv, skb, slot, false); + ret = ath9k_htc_tx_start(priv, skb); if (ret != 0) { - ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); - goto clear_slot; + if (ret == -ENOMEM) { + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Stopping TX queues\n"); + ieee80211_stop_queues(hw); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = true; + spin_unlock_bh(&priv->tx_lock); + } else { + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Tx failed\n"); + } + goto fail_tx; } - ath9k_htc_check_stop_queues(priv); - return; -clear_slot: - ath9k_htc_tx_clear_slot(priv, slot); fail_tx: dev_kfree_skb_any(skb); } @@ -942,7 +1122,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) ath9k_host_rx_init(priv); - ret = ath9k_htc_update_cap_target(priv, 0); + ret = ath9k_htc_update_cap_target(priv); if (ret) ath_dbg(common, ATH_DBG_CONFIG, "Failed to update capability in target\n"); @@ -950,15 +1130,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) priv->op_flags &= ~OP_INVALID; htc_start(priv->htc); - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; - spin_unlock_bh(&priv->tx.tx_lock); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); ieee80211_wake_queues(hw); - mod_timer(&priv->tx.cleanup_timer, - jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); - if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, AR_STOMP_LOW_WLAN_WGHT); @@ -975,7 +1152,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); - int ret __attribute__ ((unused)); + int ret = 0; u8 cmd_rsp; mutex_lock(&priv->mutex); @@ -987,16 +1164,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) } ath9k_htc_ps_wakeup(priv); - + htc_stop(priv->htc); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); + tasklet_kill(&priv->swba_tasklet); tasklet_kill(&priv->rx_tasklet); + tasklet_kill(&priv->tx_tasklet); - del_timer_sync(&priv->tx.cleanup_timer); - ath9k_htc_tx_drain(priv); - ath9k_wmi_event_drain(priv); + skb_queue_purge(&priv->tx_queue); mutex_unlock(&priv->mutex); @@ -1068,13 +1245,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: - hvif.opmode = HTC_M_STA; + hvif.opmode = cpu_to_be32(HTC_M_STA); break; case NL80211_IFTYPE_ADHOC: - hvif.opmode = HTC_M_IBSS; + hvif.opmode = cpu_to_be32(HTC_M_IBSS); break; case NL80211_IFTYPE_AP: - hvif.opmode = HTC_M_HOSTAP; + hvif.opmode = cpu_to_be32(HTC_M_HOSTAP); break; default: ath_err(common, @@ -1104,20 +1281,14 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, priv->vif_slot |= (1 << avp->index); priv->nvifs++; + priv->vif = vif; INC_VIF(priv, vif->type); - - if ((vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_ADHOC)) - ath9k_htc_assign_bslot(priv, vif); - ath9k_htc_set_opmode(priv); if ((priv->ah->opmode == NL80211_IFTYPE_AP) && - !(priv->op_flags & OP_ANI_RUNNING)) { - ath9k_hw_set_tsfadjust(priv->ah, 1); + !(priv->op_flags & OP_ANI_RUNNING)) ath9k_htc_start_ani(priv); - } ath_dbg(common, ATH_DBG_CONFIG, "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); @@ -1146,21 +1317,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); hvif.index = avp->index; WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); - if (ret) { - ath_err(common, "Unable to remove interface at idx: %d\n", - avp->index); - } priv->nvifs--; priv->vif_slot &= ~(1 << avp->index); ath9k_htc_remove_station(priv, vif, NULL); + priv->vif = NULL; DEC_VIF(priv, vif->type); - - if ((vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_ADHOC)) - ath9k_htc_remove_bslot(priv, vif); - ath9k_htc_set_opmode(priv); /* @@ -1330,13 +1493,10 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct ath9k_htc_priv *priv = hw->priv; - struct ath9k_htc_sta *ista; int ret; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); - ista = (struct ath9k_htc_sta *) sta->drv_priv; - htc_sta_drain(priv->htc, ista->index); ret = ath9k_htc_remove_station(priv, vif, sta); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); @@ -1484,7 +1644,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { ath_dbg(common, ATH_DBG_CONFIG, "Beacon enabled for BSS: %pM\n", bss_conf->bssid); - ath9k_htc_set_tsfadjust(priv, vif); priv->op_flags |= OP_ENABLE_BEACON; ath9k_htc_beacon_config(priv, vif); } @@ -1582,7 +1741,6 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, int ret = 0; mutex_lock(&priv->mutex); - ath9k_htc_ps_wakeup(priv); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -1600,15 +1758,14 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, break; case IEEE80211_AMPDU_TX_OPERATIONAL: ista = (struct ath9k_htc_sta *) sta->drv_priv; - spin_lock_bh(&priv->tx.tx_lock); + spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = AGGR_OPERATIONAL; - spin_unlock_bh(&priv->tx.tx_lock); + spin_unlock_bh(&priv->tx_lock); break; default: ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); } - ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); return ret; @@ -1659,55 +1816,6 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } -/* - * Currently, this is used only for selecting the minimum rate - * for management frames, rate selection for data frames remain - * unaffected. - */ -static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const struct cfg80211_bitrate_mask *mask) -{ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_rate_mask tmask; - struct ath9k_htc_vif *avp = (void *)vif->drv_priv; - int ret = 0; - u8 cmd_rsp; - - memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); - - tmask.vif_index = avp->index; - tmask.band = IEEE80211_BAND_2GHZ; - tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); - - WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); - if (ret) { - ath_err(common, - "Unable to set 2G rate mask for " - "interface at idx: %d\n", avp->index); - goto out; - } - - tmask.band = IEEE80211_BAND_5GHZ; - tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); - - WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); - if (ret) { - ath_err(common, - "Unable to set 5G rate mask for " - "interface at idx: %d\n", avp->index); - goto out; - } - - ath_dbg(common, ATH_DBG_CONFIG, - "Set bitrate masks: 0x%x, 0x%x\n", - mask->control[IEEE80211_BAND_2GHZ].legacy, - mask->control[IEEE80211_BAND_5GHZ].legacy); -out: - return ret; -} - struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, .start = ath9k_htc_start, @@ -1730,5 +1838,4 @@ struct ieee80211_ops ath9k_htc_ops = { .set_rts_threshold = ath9k_htc_set_rts_threshold, .rfkill_poll = ath9k_htc_rfkill_poll_state, .set_coverage_class = ath9k_htc_set_coverage_class, - .set_bitrate_mask = ath9k_htc_set_bitrate_mask, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index a898dac22337..4a4f27ba96af 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -53,138 +53,6 @@ int get_hw_qnum(u16 queue, int *hwq_map) } } -void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv) -{ - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.queued_cnt++; - if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) && - !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { - priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP; - ieee80211_stop_queues(priv->hw); - } - spin_unlock_bh(&priv->tx.tx_lock); -} - -void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) -{ - spin_lock_bh(&priv->tx.tx_lock); - if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) && - (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { - priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; - ieee80211_wake_queues(priv->hw); - } - spin_unlock_bh(&priv->tx.tx_lock); -} - -int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv) -{ - int slot; - - spin_lock_bh(&priv->tx.tx_lock); - slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM); - if (slot >= MAX_TX_BUF_NUM) { - spin_unlock_bh(&priv->tx.tx_lock); - return -ENOBUFS; - } - __set_bit(slot, priv->tx.tx_slot); - spin_unlock_bh(&priv->tx.tx_lock); - - return slot; -} - -void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot) -{ - spin_lock_bh(&priv->tx.tx_lock); - __clear_bit(slot, priv->tx.tx_slot); - spin_unlock_bh(&priv->tx.tx_lock); -} - -static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, - u16 qnum) -{ - enum htc_endpoint_id epid; - - switch (qnum) { - case 0: - TX_QSTAT_INC(WME_AC_VO); - epid = priv->data_vo_ep; - break; - case 1: - TX_QSTAT_INC(WME_AC_VI); - epid = priv->data_vi_ep; - break; - case 2: - TX_QSTAT_INC(WME_AC_BE); - epid = priv->data_be_ep; - break; - case 3: - default: - TX_QSTAT_INC(WME_AC_BK); - epid = priv->data_bk_ep; - break; - } - - return epid; -} - -static inline struct sk_buff_head* -get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct sk_buff_head *epid_queue = NULL; - - if (epid == priv->mgmt_ep) - epid_queue = &priv->tx.mgmt_ep_queue; - else if (epid == priv->cab_ep) - epid_queue = &priv->tx.cab_ep_queue; - else if (epid == priv->data_be_ep) - epid_queue = &priv->tx.data_be_queue; - else if (epid == priv->data_bk_ep) - epid_queue = &priv->tx.data_bk_queue; - else if (epid == priv->data_vi_ep) - epid_queue = &priv->tx.data_vi_queue; - else if (epid == priv->data_vo_ep) - epid_queue = &priv->tx.data_vo_queue; - else - ath_err(common, "Invalid EPID: %d\n", epid); - - return epid_queue; -} - -/* - * Removes the driver header and returns the TX slot number - */ -static inline int strip_drv_header(struct ath9k_htc_priv *priv, - struct sk_buff *skb) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_tx_ctl *tx_ctl; - int slot; - - tx_ctl = HTC_SKB_CB(skb); - - if (tx_ctl->epid == priv->mgmt_ep) { - struct tx_mgmt_hdr *tx_mhdr = - (struct tx_mgmt_hdr *)skb->data; - slot = tx_mhdr->cookie; - skb_pull(skb, sizeof(struct tx_mgmt_hdr)); - } else if ((tx_ctl->epid == priv->data_bk_ep) || - (tx_ctl->epid == priv->data_be_ep) || - (tx_ctl->epid == priv->data_vi_ep) || - (tx_ctl->epid == priv->data_vo_ep) || - (tx_ctl->epid == priv->cab_ep)) { - struct tx_frame_hdr *tx_fhdr = - (struct tx_frame_hdr *)skb->data; - slot = tx_fhdr->cookie; - skb_pull(skb, sizeof(struct tx_frame_hdr)); - } else { - ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); - slot = -EINVAL; - } - - return slot; -} - int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo) { @@ -211,140 +79,23 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, return error; } -static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv, - struct ath9k_htc_vif *avp, - struct sk_buff *skb, - u8 sta_idx, u8 vif_idx, u8 slot) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_mgmt *mgmt; - struct ieee80211_hdr *hdr; - struct tx_mgmt_hdr mgmt_hdr; - struct ath9k_htc_tx_ctl *tx_ctl; - u8 *tx_fhdr; - - tx_ctl = HTC_SKB_CB(skb); - hdr = (struct ieee80211_hdr *) skb->data; - - memset(tx_ctl, 0, sizeof(*tx_ctl)); - memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); - - /* - * Set the TSF adjust value for probe response - * frame also. - */ - if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { - mgmt = (struct ieee80211_mgmt *)skb->data; - mgmt->u.probe_resp.timestamp = avp->tsfadjust; - } - - tx_ctl->type = ATH9K_HTC_MGMT; - - mgmt_hdr.node_idx = sta_idx; - mgmt_hdr.vif_idx = vif_idx; - mgmt_hdr.tidno = 0; - mgmt_hdr.flags = 0; - mgmt_hdr.cookie = slot; - - mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); - if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) - mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; - else - mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - - tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); - memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); - tx_ctl->epid = priv->mgmt_ep; -} - -static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct sk_buff *skb, - u8 sta_idx, u8 vif_idx, u8 slot, - bool is_cab) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; - struct ath9k_htc_tx_ctl *tx_ctl; - struct tx_frame_hdr tx_hdr; - u32 flags = 0; - u8 *qc, *tx_fhdr; - u16 qnum; - - tx_ctl = HTC_SKB_CB(skb); - hdr = (struct ieee80211_hdr *) skb->data; - - memset(tx_ctl, 0, sizeof(*tx_ctl)); - memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); - - tx_hdr.node_idx = sta_idx; - tx_hdr.vif_idx = vif_idx; - tx_hdr.cookie = slot; - - /* - * This is a bit redundant but it helps to get - * the per-packet index quickly when draining the - * TX queue in the HIF layer. Otherwise we would - * have to parse the packet contents ... - */ - tx_ctl->sta_idx = sta_idx; - - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - tx_ctl->type = ATH9K_HTC_AMPDU; - tx_hdr.data_type = ATH9K_HTC_AMPDU; - } else { - tx_ctl->type = ATH9K_HTC_NORMAL; - tx_hdr.data_type = ATH9K_HTC_NORMAL; - } - - if (ieee80211_is_data_qos(hdr->frame_control)) { - qc = ieee80211_get_qos_ctl(hdr); - tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - } - - /* Check for RTS protection */ - if (priv->hw->wiphy->rts_threshold != (u32) -1) - if (skb->len > priv->hw->wiphy->rts_threshold) - flags |= ATH9K_HTC_TX_RTSCTS; - - /* CTS-to-self */ - if (!(flags & ATH9K_HTC_TX_RTSCTS) && - (vif && vif->bss_conf.use_cts_prot)) - flags |= ATH9K_HTC_TX_CTSONLY; - - tx_hdr.flags = cpu_to_be32(flags); - tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); - if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) - tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; - else - tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - - tx_fhdr = skb_push(skb, sizeof(tx_hdr)); - memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); - - if (is_cab) { - CAB_STAT_INC; - tx_ctl->epid = priv->cab_ep; - return; - } - - qnum = skb_get_queue_mapping(skb); - tx_ctl->epid = get_htc_epid(priv, qnum); -} - -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, - struct sk_buff *skb, - u8 slot, bool is_cab) +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_vif *vif = tx_info->control.vif; struct ath9k_htc_sta *ista; - struct ath9k_htc_vif *avp = NULL; + struct ath9k_htc_vif *avp; + struct ath9k_htc_tx_ctl tx_ctl; + enum htc_endpoint_id epid; + u16 qnum; + __le16 fc; + u8 *tx_fhdr; u8 sta_idx, vif_idx; hdr = (struct ieee80211_hdr *) skb->data; + fc = hdr->frame_control; /* * Find out on which interface this packet has to be @@ -373,430 +124,218 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, sta_idx = priv->vif_sta_pos[vif_idx]; } - if (ieee80211_is_data(hdr->frame_control)) - ath9k_htc_tx_data(priv, vif, skb, - sta_idx, vif_idx, slot, is_cab); - else - ath9k_htc_tx_mgmt(priv, avp, skb, - sta_idx, vif_idx, slot); - - - return htc_send(priv->htc, skb); -} - -static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, - struct ath9k_htc_sta *ista, u8 tid) -{ - bool ret = false; - - spin_lock_bh(&priv->tx.tx_lock); - if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) - ret = true; - spin_unlock_bh(&priv->tx.tx_lock); - - return ret; -} + memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); -static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, - struct ieee80211_vif *vif, - struct sk_buff *skb) -{ - struct ieee80211_sta *sta; - struct ieee80211_hdr *hdr; - __le16 fc; + if (ieee80211_is_data(fc)) { + struct tx_frame_hdr tx_hdr; + u32 flags = 0; + u8 *qc; - hdr = (struct ieee80211_hdr *) skb->data; - fc = hdr->frame_control; + memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); - rcu_read_lock(); + tx_hdr.node_idx = sta_idx; + tx_hdr.vif_idx = vif_idx; - sta = ieee80211_find_sta(vif, hdr->addr1); - if (!sta) { - rcu_read_unlock(); - return; - } + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + tx_ctl.type = ATH9K_HTC_AMPDU; + tx_hdr.data_type = ATH9K_HTC_AMPDU; + } else { + tx_ctl.type = ATH9K_HTC_NORMAL; + tx_hdr.data_type = ATH9K_HTC_NORMAL; + } - if (sta && conf_is_ht(&priv->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - struct ath9k_htc_sta *ista; - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - ista = (struct ath9k_htc_sta *)sta->drv_priv; - if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) { - ieee80211_start_tx_ba_session(sta, tid, 0); - spin_lock_bh(&priv->tx.tx_lock); - ista->tid_state[tid] = AGGR_PROGRESS; - spin_unlock_bh(&priv->tx.tx_lock); - } + tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; } - } - - rcu_read_unlock(); -} - -static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, - struct sk_buff *skb, - struct __wmi_event_txstatus *txs) -{ - struct ieee80211_vif *vif; - struct ath9k_htc_tx_ctl *tx_ctl; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rate; - struct ieee80211_conf *cur_conf = &priv->hw->conf; - bool txok; - int slot; - slot = strip_drv_header(priv, skb); - if (slot < 0) { - dev_kfree_skb_any(skb); - return; - } + /* Check for RTS protection */ + if (priv->hw->wiphy->rts_threshold != (u32) -1) + if (skb->len > priv->hw->wiphy->rts_threshold) + flags |= ATH9K_HTC_TX_RTSCTS; - tx_ctl = HTC_SKB_CB(skb); - txok = tx_ctl->txok; - tx_info = IEEE80211_SKB_CB(skb); - vif = tx_info->control.vif; - rate = &tx_info->status.rates[0]; + /* CTS-to-self */ + if (!(flags & ATH9K_HTC_TX_RTSCTS) && + (vif && vif->bss_conf.use_cts_prot)) + flags |= ATH9K_HTC_TX_CTSONLY; - memset(&tx_info->status, 0, sizeof(tx_info->status)); + tx_hdr.flags = cpu_to_be32(flags); + tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); + if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) + tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; + else + tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; - /* - * URB submission failed for this frame, it never reached - * the target. - */ - if (!txok || !vif || !txs) - goto send_mac80211; + tx_fhdr = skb_push(skb, sizeof(tx_hdr)); + memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); - if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK) - tx_info->flags |= IEEE80211_TX_STAT_ACK; + qnum = skb_get_queue_mapping(skb); - if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT) - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - - if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS) - rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; - - rate->count = 1; - rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE); - - if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) { - rate->flags |= IEEE80211_TX_RC_MCS; - - if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI) - rate->flags |= IEEE80211_TX_RC_SHORT_GI; + switch (qnum) { + case 0: + TX_QSTAT_INC(WME_AC_VO); + epid = priv->data_vo_ep; + break; + case 1: + TX_QSTAT_INC(WME_AC_VI); + epid = priv->data_vi_ep; + break; + case 2: + TX_QSTAT_INC(WME_AC_BE); + epid = priv->data_be_ep; + break; + case 3: + default: + TX_QSTAT_INC(WME_AC_BK); + epid = priv->data_bk_ep; + break; + } } else { - if (cur_conf->channel->band == IEEE80211_BAND_5GHZ) - rate->idx += 4; /* No CCK rates */ - } + struct tx_mgmt_hdr mgmt_hdr; - ath9k_htc_check_tx_aggr(priv, vif, skb); + memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); -send_mac80211: - spin_lock_bh(&priv->tx.tx_lock); - if (WARN_ON(--priv->tx.queued_cnt < 0)) - priv->tx.queued_cnt = 0; - spin_unlock_bh(&priv->tx.tx_lock); + tx_ctl.type = ATH9K_HTC_NORMAL; - ath9k_htc_tx_clear_slot(priv, slot); + mgmt_hdr.node_idx = sta_idx; + mgmt_hdr.vif_idx = vif_idx; + mgmt_hdr.tidno = 0; + mgmt_hdr.flags = 0; - /* Send status to mac80211 */ - ieee80211_tx_status(priv->hw, skb); -} + mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); + if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) + mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; + else + mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; -static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv, - struct sk_buff_head *queue) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(queue)) != NULL) { - ath9k_htc_tx_process(priv, skb, NULL); + tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); + memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); + epid = priv->mgmt_ep; } + + return htc_send(priv->htc, skb, epid, &tx_ctl); } -void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) +static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, + struct ath9k_htc_sta *ista, u8 tid) { - struct ath9k_htc_tx_event *event, *tmp; - - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN; - spin_unlock_bh(&priv->tx.tx_lock); - - /* - * Ensure that all pending TX frames are flushed, - * and that the TX completion/failed tasklets is killed. - */ - htc_stop(priv->htc); - tasklet_kill(&priv->wmi->wmi_event_tasklet); - tasklet_kill(&priv->tx_failed_tasklet); - - ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue); - ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue); - ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue); - ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue); - ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue); - ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue); - ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); + bool ret = false; - /* - * The TX cleanup timer has already been killed. - */ - spin_lock_bh(&priv->wmi->event_lock); - list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { - list_del(&event->list); - kfree(event); - } - spin_unlock_bh(&priv->wmi->event_lock); + spin_lock_bh(&priv->tx_lock); + if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) + ret = true; + spin_unlock_bh(&priv->tx_lock); - spin_lock_bh(&priv->tx.tx_lock); - priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN; - spin_unlock_bh(&priv->tx.tx_lock); + return ret; } -void ath9k_tx_failed_tasklet(unsigned long data) +void ath9k_tx_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ieee80211_vif *vif; + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *tx_info; + struct sk_buff *skb = NULL; + __le16 fc; - spin_lock_bh(&priv->tx.tx_lock); - if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { - spin_unlock_bh(&priv->tx.tx_lock); - return; - } - spin_unlock_bh(&priv->tx.tx_lock); + while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { - ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); -} + hdr = (struct ieee80211_hdr *) skb->data; + fc = hdr->frame_control; + tx_info = IEEE80211_SKB_CB(skb); + vif = tx_info->control.vif; -static inline bool check_cookie(struct ath9k_htc_priv *priv, - struct sk_buff *skb, - u8 cookie, u8 epid) -{ - u8 fcookie = 0; - - if (epid == priv->mgmt_ep) { - struct tx_mgmt_hdr *hdr; - hdr = (struct tx_mgmt_hdr *) skb->data; - fcookie = hdr->cookie; - } else if ((epid == priv->data_bk_ep) || - (epid == priv->data_be_ep) || - (epid == priv->data_vi_ep) || - (epid == priv->data_vo_ep) || - (epid == priv->cab_ep)) { - struct tx_frame_hdr *hdr; - hdr = (struct tx_frame_hdr *) skb->data; - fcookie = hdr->cookie; - } + memset(&tx_info->status, 0, sizeof(tx_info->status)); - if (fcookie == cookie) - return true; + if (!vif) + goto send_mac80211; - return false; -} + rcu_read_lock(); -static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv, - struct __wmi_event_txstatus *txs) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct sk_buff_head *epid_queue; - struct sk_buff *skb, *tmp; - unsigned long flags; - u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID); - - epid_queue = get_htc_epid_queue(priv, epid); - if (!epid_queue) - return NULL; - - spin_lock_irqsave(&epid_queue->lock, flags); - skb_queue_walk_safe(epid_queue, skb, tmp) { - if (check_cookie(priv, skb, txs->cookie, epid)) { - __skb_unlink(skb, epid_queue); - spin_unlock_irqrestore(&epid_queue->lock, flags); - return skb; + sta = ieee80211_find_sta(vif, hdr->addr1); + if (!sta) { + rcu_read_unlock(); + ieee80211_tx_status(priv->hw, skb); + continue; } - } - spin_unlock_irqrestore(&epid_queue->lock, flags); - - ath_dbg(common, ATH_DBG_XMIT, - "No matching packet for cookie: %d, epid: %d\n", - txs->cookie, epid); - return NULL; -} - -void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) -{ - struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event; - struct __wmi_event_txstatus *__txs; - struct sk_buff *skb; - struct ath9k_htc_tx_event *tx_pend; - int i; + /* Check if we need to start aggregation */ - for (i = 0; i < txs->cnt; i++) { - WARN_ON(txs->cnt > HTC_MAX_TX_STATUS); + if (sta && conf_is_ht(&priv->hw->conf) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + struct ath9k_htc_sta *ista; - __txs = &txs->txstatus[i]; + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + ista = (struct ath9k_htc_sta *)sta->drv_priv; - skb = ath9k_htc_tx_get_packet(priv, __txs); - if (!skb) { - /* - * Store this event, so that the TX cleanup - * routine can check later for the needed packet. - */ - tx_pend = kzalloc(sizeof(struct ath9k_htc_tx_event), - GFP_ATOMIC); - if (!tx_pend) - continue; - - memcpy(&tx_pend->txs, __txs, - sizeof(struct __wmi_event_txstatus)); - - spin_lock(&priv->wmi->event_lock); - list_add_tail(&tx_pend->list, - &priv->wmi->pending_tx_events); - spin_unlock(&priv->wmi->event_lock); - - continue; + if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { + ieee80211_start_tx_ba_session(sta, tid, 0); + spin_lock_bh(&priv->tx_lock); + ista->tid_state[tid] = AGGR_PROGRESS; + spin_unlock_bh(&priv->tx_lock); + } + } } - ath9k_htc_tx_process(priv, skb, __txs); + rcu_read_unlock(); + + send_mac80211: + /* Send status to mac80211 */ + ieee80211_tx_status(priv->hw, skb); } /* Wake TX queues if needed */ - ath9k_htc_check_wake_queues(priv); + spin_lock_bh(&priv->tx_lock); + if (priv->tx_queues_stop) { + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Waking up TX queues\n"); + ieee80211_wake_queues(priv->hw); + return; + } + spin_unlock_bh(&priv->tx_lock); } void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, bool txok) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; - struct ath9k_htc_tx_ctl *tx_ctl; - struct sk_buff_head *epid_queue; - - tx_ctl = HTC_SKB_CB(skb); - tx_ctl->txok = txok; - tx_ctl->timestamp = jiffies; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ieee80211_tx_info *tx_info; - if (!txok) { - skb_queue_tail(&priv->tx.tx_failed, skb); - tasklet_schedule(&priv->tx_failed_tasklet); + if (!skb) return; - } - epid_queue = get_htc_epid_queue(priv, ep_id); - if (!epid_queue) { + if (ep_id == priv->mgmt_ep) { + skb_pull(skb, sizeof(struct tx_mgmt_hdr)); + } else if ((ep_id == priv->data_bk_ep) || + (ep_id == priv->data_be_ep) || + (ep_id == priv->data_vi_ep) || + (ep_id == priv->data_vo_ep)) { + skb_pull(skb, sizeof(struct tx_frame_hdr)); + } else { + ath_err(common, "Unsupported TX EPID: %d\n", ep_id); dev_kfree_skb_any(skb); return; } - skb_queue_tail(epid_queue, skb); -} - -static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb) -{ - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_tx_ctl *tx_ctl; - - tx_ctl = HTC_SKB_CB(skb); - - if (time_after(jiffies, - tx_ctl->timestamp + - msecs_to_jiffies(ATH9K_HTC_TX_TIMEOUT_INTERVAL))) { - ath_dbg(common, ATH_DBG_XMIT, - "Dropping a packet due to TX timeout\n"); - return true; - } - - return false; -} - -static void ath9k_htc_tx_cleanup_queue(struct ath9k_htc_priv *priv, - struct sk_buff_head *epid_queue) -{ - bool process = false; - unsigned long flags; - struct sk_buff *skb, *tmp; - struct sk_buff_head queue; - - skb_queue_head_init(&queue); - - spin_lock_irqsave(&epid_queue->lock, flags); - skb_queue_walk_safe(epid_queue, skb, tmp) { - if (check_packet(priv, skb)) { - __skb_unlink(skb, epid_queue); - __skb_queue_tail(&queue, skb); - process = true; - } - } - spin_unlock_irqrestore(&epid_queue->lock, flags); - - if (process) { - skb_queue_walk_safe(&queue, skb, tmp) { - __skb_unlink(skb, &queue); - ath9k_htc_tx_process(priv, skb, NULL); - } - } -} - -void ath9k_htc_tx_cleanup_timer(unsigned long data) -{ - struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_tx_event *event, *tmp; - struct sk_buff *skb; - - spin_lock(&priv->wmi->event_lock); - list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { - - skb = ath9k_htc_tx_get_packet(priv, &event->txs); - if (skb) { - ath_dbg(common, ATH_DBG_XMIT, - "Found packet for cookie: %d, epid: %d\n", - event->txs.cookie, - MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID)); - - ath9k_htc_tx_process(priv, skb, &event->txs); - list_del(&event->list); - kfree(event); - continue; - } - - if (++event->count >= ATH9K_HTC_TX_TIMEOUT_COUNT) { - list_del(&event->list); - kfree(event); - } - } - spin_unlock(&priv->wmi->event_lock); - - /* - * Check if status-pending packets have to be cleaned up. - */ - ath9k_htc_tx_cleanup_queue(priv, &priv->tx.mgmt_ep_queue); - ath9k_htc_tx_cleanup_queue(priv, &priv->tx.cab_ep_queue); - ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_be_queue); - ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_bk_queue); - ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vi_queue); - ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vo_queue); + tx_info = IEEE80211_SKB_CB(skb); - /* Wake TX queues if needed */ - ath9k_htc_check_wake_queues(priv); + if (txok) + tx_info->flags |= IEEE80211_TX_STAT_ACK; - mod_timer(&priv->tx.cleanup_timer, - jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); + skb_queue_tail(&priv->tx_queue, skb); + tasklet_schedule(&priv->tx_tasklet); } int ath9k_tx_init(struct ath9k_htc_priv *priv) { - skb_queue_head_init(&priv->tx.mgmt_ep_queue); - skb_queue_head_init(&priv->tx.cab_ep_queue); - skb_queue_head_init(&priv->tx.data_be_queue); - skb_queue_head_init(&priv->tx.data_bk_queue); - skb_queue_head_init(&priv->tx.data_vi_queue); - skb_queue_head_init(&priv->tx.data_vo_queue); - skb_queue_head_init(&priv->tx.tx_failed); + skb_queue_head_init(&priv->tx_queue); return 0; } @@ -968,9 +507,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, int last_rssi = ATH_RSSI_DUMMY_MARKER; __le16 fc; - if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { - ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", - skb->len); + if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { + ath_err(common, "Corrupted RX frame, dropping\n"); goto rx_next; } @@ -984,8 +522,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, goto rx_next; } - ath9k_htc_err_stat_rx(priv, rxstatus); - /* Get the RX status information */ memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c b/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c index 5c76352b1319..c41ab8c30161 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -17,8 +17,8 @@ #include "htc.h" static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, - u16 len, u8 flags, u8 epid) - + u16 len, u8 flags, u8 epid, + struct ath9k_htc_tx_ctl *tx_ctl) { struct htc_frame_hdr *hdr; struct htc_endpoint *endpoint = &target->endpoint[epid]; @@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, hdr->flags = flags; hdr->payload_len = cpu_to_be16(len); - status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); - + status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, + tx_ctl); return status; } @@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target) target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); if (ret) goto err; @@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target) target->htc_flags |= HTC_OP_START_WAIT; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); if (ret) goto err; @@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target, conn_msg->dl_pipeid = endpoint->dl_pipeid; conn_msg->ul_pipeid = endpoint->ul_pipeid; - ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); + ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); if (ret) goto err; @@ -286,33 +286,35 @@ int htc_connect_service(struct htc_target *target, return ret; } -int htc_send(struct htc_target *target, struct sk_buff *skb) +int htc_send(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) { - struct ath9k_htc_tx_ctl *tx_ctl; - - tx_ctl = HTC_SKB_CB(skb); - return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid); -} - -int htc_send_epid(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id epid) -{ - return htc_issue_send(target, skb, skb->len, 0, epid); + return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); } void htc_stop(struct htc_target *target) { - target->hif->stop(target->hif_dev); + enum htc_endpoint_id epid; + struct htc_endpoint *endpoint; + + for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { + endpoint = &target->endpoint[epid]; + if (endpoint->service_id != 0) + target->hif->stop(target->hif_dev, endpoint->ul_pipeid); + } } void htc_start(struct htc_target *target) { - target->hif->start(target->hif_dev); -} + enum htc_endpoint_id epid; + struct htc_endpoint *endpoint; -void htc_sta_drain(struct htc_target *target, u8 idx) -{ - target->hif->sta_drain(target->hif_dev, idx); + for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { + endpoint = &target->endpoint[epid]; + if (endpoint->service_id != 0) + target->hif->start(target->hif_dev, + endpoint->ul_pipeid); + } } void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_hst.h b/trunk/drivers/net/wireless/ath/ath9k/htc_hst.h index 91a5305db95a..ecd018798c47 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -33,10 +33,10 @@ struct ath9k_htc_hif { u8 control_dl_pipe; u8 control_ul_pipe; - void (*start) (void *hif_handle); - void (*stop) (void *hif_handle); - void (*sta_drain) (void *hif_handle, u8 idx); - int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); + void (*start) (void *hif_handle, u8 pipe); + void (*stop) (void *hif_handle, u8 pipe); + int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, + struct ath9k_htc_tx_ctl *tx_ctl); }; enum htc_endpoint_id { @@ -83,10 +83,21 @@ struct htc_ep_callbacks { void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); }; +#define HTC_TX_QUEUE_SIZE 256 + +struct htc_txq { + struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; + u32 txqdepth; + u16 txbuf_cnt; + u16 txq_head; + u16 txq_tail; +}; + struct htc_endpoint { u16 service_id; struct htc_ep_callbacks ep_callbacks; + struct htc_txq htc_txq; u32 max_txqdepth; int max_msglen; @@ -194,12 +205,10 @@ int htc_init(struct htc_target *target); int htc_connect_service(struct htc_target *target, struct htc_service_connreq *service_connreq, enum htc_endpoint_id *conn_rsp_eid); -int htc_send(struct htc_target *target, struct sk_buff *skb); -int htc_send_epid(struct htc_target *target, struct sk_buff *skb, - enum htc_endpoint_id epid); +int htc_send(struct htc_target *target, struct sk_buff *skb, + enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); void htc_stop(struct htc_target *target); void htc_start(struct htc_target *target); -void htc_sta_drain(struct htc_target *target, u8 idx); void ath9k_htc_rx_msg(struct htc_target *htc_handle, struct sk_buff *skb, u32 len, u8 pipe_id); diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h b/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h index 9dd90a85ad63..c8f254fe0f0b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -122,9 +122,10 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); } -static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, + u32 vmf) { - ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); + ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); } /* Private hardware call ops */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 58f3d4210338..c95bc5cc1a1f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -130,20 +130,6 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) } EXPORT_SYMBOL(ath9k_hw_wait); -void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, - int column, unsigned int *writecnt) -{ - int r; - - ENABLE_REGWRITE_BUFFER(ah); - for (r = 0; r < array->ia_rows; r++) { - REG_WRITE(ah, INI_RA(array, r, 0), - INI_RA(array, r, column)); - DO_DELAY(*writecnt); - } - REGWRITE_BUFFER_FLUSH(ah); -} - u32 ath9k_hw_reverse_bits(u32 val, u32 n) { u32 retval; @@ -156,6 +142,25 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n) return retval; } +bool ath9k_get_channel_edges(struct ath_hw *ah, + u16 flags, u16 *low, + u16 *high) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + + if (flags & CHANNEL_5GHZ) { + *low = pCap->low_5ghz_chan; + *high = pCap->high_5ghz_chan; + return true; + } + if ((flags & CHANNEL_2GHZ)) { + *low = pCap->low_2ghz_chan; + *high = pCap->high_2ghz_chan; + return true; + } + return false; +} + u16 ath9k_hw_computetxtime(struct ath_hw *ah, u8 phy, int kbps, u32 frameLen, u16 rateix, @@ -247,17 +252,6 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) { u32 val; - switch (ah->hw_version.devid) { - case AR5416_AR9100_DEVID: - ah->hw_version.macVersion = AR_SREV_VERSION_9100; - break; - case AR9300_DEVID_AR9340: - ah->hw_version.macVersion = AR_SREV_VERSION_9340; - val = REG_READ(ah, AR_SREV); - ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); - return; - } - val = REG_READ(ah, AR_SREV) & AR_SREV_ID; if (val == 0xFF) { @@ -370,6 +364,11 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } + if (ah->hw_version.devid != AR2427_DEVID_PCIE) + ah->config.ht_enable = 1; + else + ah->config.ht_enable = 0; + /* PAPRD needs some more work to be enabled */ ah->config.paprd_disable = 1; @@ -411,8 +410,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | AR_STA_ID1_MCAST_KSRCH; - if (AR_SREV_9100(ah)) - ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ah->enable_32kHz_clock = DONT_USE_32KHZ; ah->slottime = 20; ah->globaltxtimeout = (u32) -1; @@ -473,7 +470,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return ecode; } - if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { + if (!AR_SREV_9100(ah)) { ath9k_hw_ani_setup(ah); ath9k_hw_ani_init(ah); } @@ -495,6 +492,9 @@ static int __ath9k_hw_init(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); int r = 0; + if (ah->hw_version.devid == AR5416_AR9100_DEVID) + ah->hw_version.macVersion = AR_SREV_VERSION_9100; + ath9k_hw_read_revisions(ah); /* @@ -552,7 +552,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) case AR_SREV_VERSION_9271: case AR_SREV_VERSION_9300: case AR_SREV_VERSION_9485: - case AR_SREV_VERSION_9340: break; default: ath_err(common, @@ -561,7 +560,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) return -EOPNOTSUPP; } - if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah)) + if (AR_SREV_9271(ah) || AR_SREV_9100(ah)) ah->is_pciexpress = false; ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); @@ -630,7 +629,6 @@ int ath9k_hw_init(struct ath_hw *ah) case AR2427_DEVID_PCIE: case AR9300_DEVID_PCIE: case AR9300_DEVID_AR9485_PCIE: - case AR9300_DEVID_AR9340: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) @@ -673,89 +671,48 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REGWRITE_BUFFER_FLUSH(ah); } -u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) +unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) { - REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); - udelay(100); - REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); - - while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) + REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK))); udelay(100); + REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK)); - return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; + while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) + udelay(100); + + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); +#define DPLL2_KD_VAL 0x3D +#define DPLL2_KI_VAL 0x06 +#define DPLL3_PHASE_SHIFT_VAL 0x1 + static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { u32 pll; if (AR_SREV_9485(ah)) { + REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); + REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01); - /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_BB_DPLL2_PLL_PWD, 0x1); - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_DPLL2_KD, 0x40); - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_DPLL2_KI, 0x4); - - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, - AR_CH0_BB_DPLL1_REFDIV, 0x5); - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, - AR_CH0_BB_DPLL1_NINI, 0x58); - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, - AR_CH0_BB_DPLL1_NFRAC, 0x0); - - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_BB_DPLL2_OUTDIV, 0x1); - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1); - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); - - /* program BB PLL phase_shift to 0x6 */ - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, - AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); - - REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, - AR_CH0_BB_DPLL2_PLL_PWD, 0x0); - udelay(1000); - } else if (AR_SREV_9340(ah)) { - u32 regval, pll2_divint, pll2_divfrac, refdiv; + REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, + AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); udelay(1000); - REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16); - udelay(100); - - if (ah->is_clk_25mhz) { - pll2_divint = 0x54; - pll2_divfrac = 0x1eb85; - refdiv = 3; - } else { - pll2_divint = 88; - pll2_divfrac = 0; - refdiv = 5; - } - - regval = REG_READ(ah, AR_PHY_PLL_MODE); - regval |= (0x1 << 16); - REG_WRITE(ah, AR_PHY_PLL_MODE, regval); - udelay(100); + REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); - REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) | - (pll2_divint << 18) | pll2_divfrac); - udelay(100); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KD, DPLL2_KD_VAL); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KI, DPLL2_KI_VAL); - regval = REG_READ(ah, AR_PHY_PLL_MODE); - regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | - (0x4 << 26) | (0x18 << 19); - REG_WRITE(ah, AR_PHY_PLL_MODE, regval); - REG_WRITE(ah, AR_PHY_PLL_MODE, - REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, + AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); + REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); udelay(1000); } @@ -763,9 +720,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) - udelay(1000); - /* Switch the core clock for ar9271 to 117Mhz */ if (AR_SREV_9271(ah)) { udelay(500); @@ -775,34 +729,17 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, udelay(RTC_PLL_SETTLE_DELAY); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); - - if (AR_SREV_9340(ah)) { - if (ah->is_clk_25mhz) { - REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); - REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); - REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); - } else { - REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); - REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); - REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); - } - udelay(100); - } } static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, enum nl80211_iftype opmode) { - u32 sync_default = AR_INTR_SYNC_DEFAULT; u32 imr_reg = AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_BCNMISC; - if (AR_SREV_9340(ah)) - sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; - if (AR_SREV_9300_20_OR_LATER(ah)) { imr_reg |= AR_IMR_RXOK_HP; if (ah->config.rx_intr_mitigation) @@ -833,7 +770,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, if (!AR_SREV_9100(ah)) { REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); } @@ -893,7 +830,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) ah->misc_mode); if (ah->misc_mode != 0) - REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); + REG_WRITE(ah, AR_PCU_MISC, + REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) sifstime = 16; @@ -961,19 +899,23 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) static inline void ath9k_hw_set_dma(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); + u32 regval; ENABLE_REGWRITE_BUFFER(ah); /* * set AHB_MODE not to do cacheline prefetches */ - if (!AR_SREV_9300_20_OR_LATER(ah)) - REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); + if (!AR_SREV_9300_20_OR_LATER(ah)) { + regval = REG_READ(ah, AR_AHB_MODE); + REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); + } /* * let mac dma reads be in 128 byte chunks */ - REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK); + regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; + REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); REGWRITE_BUFFER_FLUSH(ah); @@ -990,7 +932,8 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) /* * let mac dma writes be in 128 byte chunks */ - REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK); + regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; + REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); /* * Setup receive FIFO threshold to hold off TX activities @@ -1029,27 +972,30 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) { - u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; - u32 set = AR_STA_ID1_KSRCH_MODE; + u32 val; + val = REG_READ(ah, AR_STA_ID1); + val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); switch (opmode) { + case NL80211_IFTYPE_AP: + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP + | AR_STA_ID1_KSRCH_MODE); + REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: - set |= AR_STA_ID1_ADHOC; + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC + | AR_STA_ID1_KSRCH_MODE); REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; - case NL80211_IFTYPE_AP: - set |= AR_STA_ID1_STA_AP; - /* fall through */ case NL80211_IFTYPE_STATION: - REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); break; default: - if (!ah->is_monitoring) - set = 0; + if (ah->is_monitoring) + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); break; } - REG_RMW(ah, AR_STA_ID1, set, mask); } void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, @@ -1075,8 +1021,10 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) u32 tmpReg; if (AR_SREV_9100(ah)) { - REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK, - AR_RTC_DERIVED_CLK_PERIOD, 1); + u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); + val &= ~AR_RTC_DERIVED_CLK_PERIOD; + val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); + REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); (void)REG_READ(ah, AR_RTC_DERIVED_CLK); } @@ -1264,20 +1212,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return true; } -static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) -{ - u32 gpio_mask = ah->gpio_mask; - int i; - - for (i = 0; gpio_mask; i++, gpio_mask >>= 1) { - if (!(gpio_mask & 1)) - continue; - - ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); - } -} - bool ath9k_hw_check_alive(struct ath_hw *ah) { int count = 50; @@ -1475,7 +1409,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); ah->intr_txqs = 0; - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + for (i = 0; i < ah->caps.total_queues; i++) ath9k_hw_resettxqueue(ah, i); ath9k_hw_init_interrupt_masks(ah, ah->opmode); @@ -1492,7 +1426,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ar9002_hw_enable_wep_aggregation(ah); } - REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); + REG_WRITE(ah, AR_STA_ID1, + REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); ath9k_hw_set_dma(ah); @@ -1545,9 +1480,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); } #ifdef __BIG_ENDIAN - else if (AR_SREV_9340(ah)) - REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); - else + else REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); #endif } @@ -1558,8 +1491,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9300_20_OR_LATER(ah)) ar9003_hw_bb_watchdog_config(ah); - ath9k_hw_apply_gpio_override(ah); - return 0; } EXPORT_SYMBOL(ath9k_hw_reset); @@ -1739,15 +1670,21 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) case NL80211_IFTYPE_MESH_POINT: REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); - REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + - TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); + REG_WRITE(ah, AR_NEXT_NDP_TIMER, + TU_TO_USEC(next_beacon + + (ah->atim_window ? ah-> + atim_window : 1))); flags |= AR_NDP_TIMER_EN; case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - - TU_TO_USEC(ah->config.dma_beacon_response_time)); - REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - - TU_TO_USEC(ah->config.sw_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); + REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, + TU_TO_USEC(next_beacon - + ah->config. + dma_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_SWBA, + TU_TO_USEC(next_beacon - + ah->config. + sw_beacon_response_time)); flags |= AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; break; @@ -1759,13 +1696,18 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) break; } - REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); - REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); - REG_WRITE(ah, AR_NDP_PERIOD, beacon_period); + REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); REGWRITE_BUFFER_FLUSH(ah); + beacon_period &= ~ATH9K_BEACON_ENA; + if (beacon_period & ATH9K_BEACON_RESET_TSF) { + ath9k_hw_reset_tsf(ah); + } + REG_SET_BIT(ah, AR_TIMER_MODE, flags); } EXPORT_SYMBOL(ath9k_hw_beaconinit); @@ -1853,7 +1795,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - u16 eeval; + u16 capField = 0, eeval; u8 ant_div_ctl1, tx_chainmask, rx_chainmask; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); @@ -1864,6 +1806,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) eeval |= AR9285_RDEXT_DEFAULT; regulatory->current_rd_ext = eeval; + capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); + if (ah->opmode != NL80211_IFTYPE_AP && ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { if (regulatory->current_rd == 0x64 || @@ -1898,8 +1842,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) !(AR_SREV_9271(ah))) /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; - else if (AR_SREV_9100(ah)) - pCap->rx_chainmask = 0x7; else /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); @@ -1910,13 +1852,36 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9300_20_OR_LATER(ah)) ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; + pCap->low_2ghz_chan = 2312; + pCap->high_2ghz_chan = 2732; + + pCap->low_5ghz_chan = 4920; + pCap->high_5ghz_chan = 6100; + common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; - if (ah->hw_version.devid != AR2427_DEVID_PCIE) + if (ah->config.ht_enable) pCap->hw_caps |= ATH9K_HW_CAP_HT; else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; + if (capField & AR_EEPROM_EEPCAP_MAXQCU) + pCap->total_queues = + MS(capField, AR_EEPROM_EEPCAP_MAXQCU); + else + pCap->total_queues = ATH9K_NUM_TX_QUEUES; + + if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) + pCap->keycache_size = + 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); + else + pCap->keycache_size = AR_KEYTABLE_SIZE; + + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; + else + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; + if (AR_SREV_9271(ah)) pCap->num_gpio_pins = AR9271_NUM_GPIO; else if (AR_DEVID_7010(ah)) @@ -1935,6 +1900,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rts_aggr_limit = (8 * 1024); } + pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; + #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); if (ah->rfsilent & EEP_RFSILENT_ENABLED) { @@ -1956,23 +1923,32 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - if (common->btcoex_enabled) { - if (AR_SREV_9300_20_OR_LATER(ah)) { + if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { + pCap->reg_cap = + AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | + AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | + AR_EEPROM_EEREGCAP_EN_KK_U2 | + AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; + } else { + pCap->reg_cap = + AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | + AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; + } + + /* Advertise midband for AR5416 with FCC midband set in eeprom */ + if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && + AR_SREV_5416(ah)) + pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; + + if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { + btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; + btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; + + if (AR_SREV_9285(ah)) { btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; - btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; - btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300; - } else if (AR_SREV_9280_20_OR_LATER(ah)) { - btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280; - btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280; - - if (AR_SREV_9285(ah)) { - btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_hw->btpriority_gpio = - ATH_BTPRIORITY_GPIO_9285; - } else { - btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; - } + btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; + } else { + btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; } } else { btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; @@ -2210,9 +2186,11 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) REG_WRITE(ah, AR_PHY_ERR, phybits); if (phybits) - REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); + REG_WRITE(ah, AR_RXCFG, + REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); else - REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); + REG_WRITE(ah, AR_RXCFG, + REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); REGWRITE_BUFFER_FLUSH(ah); } @@ -2388,11 +2366,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) return timer_table->gen_timer_index[b]; } -u32 ath9k_hw_gettsf32(struct ath_hw *ah) +static u32 ath9k_hw_gettsf32(struct ath_hw *ah) { return REG_READ(ah, AR_TSF_L32); } -EXPORT_SYMBOL(ath9k_hw_gettsf32); struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), @@ -2425,11 +2402,11 @@ EXPORT_SYMBOL(ath_gen_timer_alloc); void ath9k_hw_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, - u32 trig_timeout, + u32 timer_next, u32 timer_period) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - u32 tsf, timer_next; + u32 tsf; BUG_ON(!timer_period); @@ -2437,12 +2414,17 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, tsf = ath9k_hw_gettsf32(ah); - timer_next = tsf + trig_timeout; - ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER, "current tsf %x period %x timer_next %x\n", tsf, timer_period, timer_next); + /* + * Pull timer_next forward if the current TSF already passed it + * because of software latency + */ + if (timer_next < tsf) + timer_next = tsf + timer_period; + /* * Program generic timer registers */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 34ed1bd0e855..6650fd48415c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -43,7 +43,6 @@ #define AR9287_DEVID_PCI 0x002d #define AR9287_DEVID_PCIE 0x002e #define AR9300_DEVID_PCIE 0x0030 -#define AR9300_DEVID_AR9340 0x0031 #define AR9300_DEVID_AR9485_PCIE 0x0032 #define AR5416_AR9100_DEVID 0x000b @@ -56,9 +55,6 @@ #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab -#define AR9300_NUM_BT_WEIGHTS 4 -#define AR9300_NUM_WLAN_WEIGHTS 4 - #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) #define ATH_DEFAULT_NOISE_FLOOR -95 @@ -69,49 +65,53 @@ /* Register read/write primitives */ #define REG_WRITE(_ah, _reg, _val) \ - (_ah)->reg_ops.write((_ah), (_val), (_reg)) + ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) #define REG_READ(_ah, _reg) \ - (_ah)->reg_ops.read((_ah), (_reg)) + ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) #define REG_READ_MULTI(_ah, _addr, _val, _cnt) \ - (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt)) - -#define REG_RMW(_ah, _reg, _set, _clr) \ - (_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr)) + ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt)) #define ENABLE_REGWRITE_BUFFER(_ah) \ do { \ - if ((_ah)->reg_ops.enable_write_buffer) \ - (_ah)->reg_ops.enable_write_buffer((_ah)); \ + if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \ + ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ } while (0) #define REGWRITE_BUFFER_FLUSH(_ah) \ do { \ - if ((_ah)->reg_ops.write_flush) \ - (_ah)->reg_ops.write_flush((_ah)); \ + if (ath9k_hw_common(_ah)->ops->write_flush) \ + ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ } while (0) #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) +#define REG_RMW(_a, _r, _set, _clr) \ + REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) #define REG_RMW_FIELD(_a, _r, _f, _v) \ - REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f)) + REG_WRITE(_a, _r, \ + (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) #define REG_READ_FIELD(_a, _r, _f) \ (((REG_READ(_a, _r) & _f) >> _f##_S)) #define REG_SET_BIT(_a, _r, _f) \ - REG_RMW(_a, _r, (_f), 0) + REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f)) #define REG_CLR_BIT(_a, _r, _f) \ - REG_RMW(_a, _r, 0, (_f)) + REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f)) -#define DO_DELAY(x) do { \ - if (((++(x) % 64) == 0) && \ - (ath9k_hw_common(ah)->bus_ops->ath_bus_type \ - != ATH_USB)) \ - udelay(1); \ +#define DO_DELAY(x) do { \ + if ((++(x) % 64) == 0) \ + udelay(1); \ } while (0) -#define REG_WRITE_ARRAY(iniarray, column, regWr) \ - ath9k_hw_write_array(ah, iniarray, column, &(regWr)) +#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ + int r; \ + for (r = 0; r < ((iniarray)->ia_rows); r++) { \ + REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ + INI_RA((iniarray), r, (column))); \ + DO_DELAY(regWr); \ + } \ + } while (0) #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 @@ -125,7 +125,7 @@ #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) #define BASE_ACTIVATE_DELAY 100 -#define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100) +#define RTC_PLL_SETTLE_DELAY 100 #define COEF_SCALE_S 24 #define HT40_CHANNEL_CENTER_SHIFT 10 @@ -178,6 +178,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_HT = BIT(0), ATH9K_HW_CAP_RFSILENT = BIT(1), ATH9K_HW_CAP_CST = BIT(2), + ATH9K_HW_CAP_ENHANCEDPM = BIT(3), ATH9K_HW_CAP_AUTOSLEEP = BIT(4), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), ATH9K_HW_CAP_EDMA = BIT(6), @@ -194,11 +195,17 @@ enum ath9k_hw_caps { struct ath9k_hw_capabilities { u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ + u16 total_queues; + u16 keycache_size; + u16 low_5ghz_chan, high_5ghz_chan; + u16 low_2ghz_chan, high_2ghz_chan; u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; u8 max_txchains; u8 max_rxchains; + u16 tx_triglevel_max; + u16 reg_cap; u8 num_gpio_pins; u8 rx_hp_qdepth; u8 rx_lp_qdepth; @@ -220,6 +227,7 @@ struct ath9k_ops_config { u8 pcie_clock_req; u32 pcie_waen; u8 analog_shiftreg; + u8 ht_enable; u8 paprd_disable; u32 ofdm_trig_low; u32 ofdm_trig_high; @@ -404,6 +412,8 @@ struct ath9k_beacon_state { u32 bs_nextdtim; u32 bs_intval; #define ATH9K_BEACON_PERIOD 0x0000ffff +#define ATH9K_BEACON_ENA 0x00800000 +#define ATH9K_BEACON_RESET_TSF 0x01000000 #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ u32 bs_dtimperiod; u16 bs_cfpperiod; @@ -630,7 +640,8 @@ struct ath_hw_ops { void (*clr11n_aggr)(struct ath_hw *ah, void *ds); void (*set11n_burstduration)(struct ath_hw *ah, void *ds, u32 burstDuration); - void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); + void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, + u32 vmf); }; struct ath_nf_limits { @@ -644,8 +655,6 @@ struct ath_nf_limits { #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ struct ath_hw { - struct ath_ops reg_ops; - struct ieee80211_hw *hw; struct ath_common common; struct ath9k_hw_version hw_version; @@ -775,8 +784,6 @@ struct ath_hw { /* Bluetooth coexistance */ struct ath_btcoex_hw btcoex_hw; - u32 bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS]; - u32 bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; u32 intr_txqs; u8 txchainmask; @@ -787,9 +794,7 @@ struct ath_hw { u32 originalGain[22]; int initPDADC; int PDADCdelta; - int led_pin; - u32 gpio_mask; - u32 gpio_val; + u8 led_pin; struct ar5416IniArray iniModes; struct ar5416IniArray iniCommon; @@ -805,7 +810,6 @@ struct ath_hw { struct ar5416IniArray iniPcieSerdes; struct ar5416IniArray iniPcieSerdesLowPower; struct ar5416IniArray iniModesAdditional; - struct ar5416IniArray iniModesAdditional_40M; struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesTxGain; struct ar5416IniArray iniModes_9271_1_0_only; @@ -852,16 +856,6 @@ struct ath_hw { /* Enterprise mode cap */ u32 ent_mode; - - bool is_clk_25mhz; -}; - -struct ath_bus_ops { - enum ath_bus_type ath_bus_type; - void (*read_cachesize)(struct ath_common *common, int *csz); - bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); - void (*bt_coex_prep)(struct ath_common *common); - void (*extn_synch_en)(struct ath_common *common); }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) @@ -913,9 +907,8 @@ void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, /* General Operation */ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); -void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, - int column, unsigned int *writecnt); u32 ath9k_hw_reverse_bits(u32 val, u32 n); +bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); u16 ath9k_hw_computetxtime(struct ath_hw *ah, u8 phy, int kbps, u32 frameLen, u16 rateix, bool shortPreamble); @@ -931,13 +924,12 @@ void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); void ath9k_hw_setbssidmask(struct ath_hw *ah); void ath9k_hw_write_associd(struct ath_hw *ah); -u32 ath9k_hw_gettsf32(struct ath_hw *ah); u64 ath9k_hw_gettsf64(struct ath_hw *ah); void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); void ath9k_hw_init_global_settings(struct ath_hw *ah); -u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); +unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index b172d1509515..79aec983279f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -15,7 +15,6 @@ */ #include -#include #include "ath9k.h" @@ -196,27 +195,10 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) return val; } -static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) -{ - struct ath_hw *ah = (struct ath_hw *) hw_priv; - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - unsigned long uninitialized_var(flags); - u32 val; - - if (ah->config.serialize_regmode == SER_REG_MODE_ON) - spin_lock_irqsave(&sc->sc_serial_rw, flags); - - val = ioread32(sc->mem + reg_offset); - val &= ~clr; - val |= set; - iowrite32(val, sc->mem + reg_offset); - - if (ah->config.serialize_regmode == SER_REG_MODE_ON) - spin_unlock_irqrestore(&sc->sc_serial_rw, flags); - - return val; -} +static const struct ath_ops ath9k_common_ops = { + .read = ath9k_ioread32, + .write = ath9k_iowrite32, +}; /**************************/ /* Initialization */ @@ -407,7 +389,13 @@ void ath9k_init_crypto(struct ath_softc *sc) int i = 0; /* Get the hardware key cache size. */ - common->keymax = AR_KEYTABLE_SIZE; + common->keymax = sc->sc_ah->caps.keycache_size; + if (common->keymax > ATH_KEYMAX) { + ath_dbg(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); + common->keymax = ATH_KEYMAX; + } /* * Reset the key cache since some parts do not @@ -549,7 +537,6 @@ static void ath9k_init_misc(struct ath_softc *sc) static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops) { - struct ath9k_platform_data *pdata = sc->dev->platform_data; struct ath_hw *ah = NULL; struct ath_common *common; int ret = 0, i; @@ -562,23 +549,13 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, ah->hw = sc->hw; ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; - ah->reg_ops.read = ath9k_ioread32; - ah->reg_ops.write = ath9k_iowrite32; - ah->reg_ops.rmw = ath9k_reg_rmw; sc->sc_ah = ah; - if (!pdata) { + if (!sc->dev->platform_data) ah->ah_flags |= AH_USE_EEPROM; - sc->sc_ah->led_pin = -1; - } else { - sc->sc_ah->gpio_mask = pdata->gpio_mask; - sc->sc_ah->gpio_val = pdata->gpio_val; - sc->sc_ah->led_pin = pdata->led_pin; - ah->is_clk_25mhz = pdata->is_clk_25mhz; - } common = ath9k_hw_common(ah); - common->ops = &ah->reg_ops; + common->ops = &ath9k_common_ops; common->bus_ops = bus_ops; common->ah = ah; common->hw = sc->hw; @@ -610,9 +587,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, if (ret) goto err_hw; - if (pdata && pdata->macaddr) - memcpy(common->macaddr, pdata->macaddr, ETH_ALEN); - ret = ath9k_init_queues(sc); if (ret) goto err_queues; @@ -705,8 +679,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) if (AR_SREV_5416(sc->sc_ah)) hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; - hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; @@ -801,7 +773,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, INIT_WORK(&sc->hw_check_work, ath_hw_check); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); - INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); sc->last_rssi = ATH_RSSI_DUMMY_MARKER; ath_init_leds(sc); diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.c b/trunk/drivers/net/wireless/ath/ath9k/mac.c index 9cf7a7d0e118..edc1cbbfecaf 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.c @@ -209,8 +209,15 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, { u32 cw; struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_tx_queue_info *qi; + if (q >= pCap->total_queues) { + ath_dbg(common, ATH_DBG_QUEUE, + "Set TXQ properties, invalid queue: %u\n", q); + return false; + } + qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -273,8 +280,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qinfo) { struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_tx_queue_info *qi; + if (q >= pCap->total_queues) { + ath_dbg(common, ATH_DBG_QUEUE, + "Get TXQ properties, invalid queue: %u\n", q); + return false; + } + qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -306,27 +320,28 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info *qi; + struct ath9k_hw_capabilities *pCap = &ah->caps; int q; switch (type) { case ATH9K_TX_QUEUE_BEACON: - q = ATH9K_NUM_TX_QUEUES - 1; + q = pCap->total_queues - 1; break; case ATH9K_TX_QUEUE_CAB: - q = ATH9K_NUM_TX_QUEUES - 2; + q = pCap->total_queues - 2; break; case ATH9K_TX_QUEUE_PSPOLL: q = 1; break; case ATH9K_TX_QUEUE_UAPSD: - q = ATH9K_NUM_TX_QUEUES - 3; + q = pCap->total_queues - 3; break; case ATH9K_TX_QUEUE_DATA: - for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) + for (q = 0; q < pCap->total_queues; q++) if (ah->txq[q].tqi_type == ATH9K_TX_QUEUE_INACTIVE) break; - if (q == ATH9K_NUM_TX_QUEUES) { + if (q == pCap->total_queues) { ath_err(common, "No available TX queue\n"); return -1; } @@ -367,9 +382,15 @@ EXPORT_SYMBOL(ath9k_hw_setuptxqueue); bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) { + struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info *qi; + if (q >= pCap->total_queues) { + ath_dbg(common, ATH_DBG_QUEUE, + "Release TXQ, invalid queue: %u\n", q); + return false; + } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -393,11 +414,18 @@ EXPORT_SYMBOL(ath9k_hw_releasetxqueue); bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) { + struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; struct ath9k_tx_queue_info *qi; u32 cwMin, chanCwMin, value; + if (q >= pCap->total_queues) { + ath_dbg(common, ATH_DBG_QUEUE, + "Reset TXQ, invalid queue: %u\n", q); + return false; + } + qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { ath_dbg(common, ATH_DBG_QUEUE, @@ -437,9 +465,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REG_WRITE(ah, AR_QCBRCFG(q), SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); - REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR | - (qi->tqi_cbrOverflowLimit ? - AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); + REG_WRITE(ah, AR_QMISC(q), + REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | + (qi->tqi_cbrOverflowLimit ? + AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); } if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { REG_WRITE(ah, AR_QRDYTIMECFG(q), @@ -452,31 +481,40 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); if (qi->tqi_burstTime - && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) - REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY); + && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { + REG_WRITE(ah, AR_QMISC(q), + REG_READ(ah, AR_QMISC(q)) | + AR_Q_MISC_RDYTIME_EXP_POLICY); - if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) - REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); + } - REGWRITE_BUFFER_FLUSH(ah); + if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { + REG_WRITE(ah, AR_DMISC(q), + REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_POST_FR_BKOFF_DIS); + } - if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) - REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN); + REGWRITE_BUFFER_FLUSH(ah); + if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { + REG_WRITE(ah, AR_DMISC(q), + REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_FRAG_BKOFF_EN); + } switch (qi->tqi_type) { case ATH9K_TX_QUEUE_BEACON: ENABLE_REGWRITE_BUFFER(ah); - REG_SET_BIT(ah, AR_QMISC(q), - AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_BEACON_USE - | AR_Q_MISC_CBR_INCR_DIS1); + REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1); - REG_SET_BIT(ah, AR_DMISC(q), - (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << + REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) + | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S) - | AR_D_MISC_BEACON_USE - | AR_D_MISC_POST_FR_BKOFF_DIS); + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS); REGWRITE_BUFFER_FLUSH(ah); @@ -495,38 +533,41 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) case ATH9K_TX_QUEUE_CAB: ENABLE_REGWRITE_BUFFER(ah); - REG_SET_BIT(ah, AR_QMISC(q), - AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_CBR_INCR_DIS1 - | AR_Q_MISC_CBR_INCR_DIS0); + REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0); value = (qi->tqi_readyTime - (ah->config.sw_beacon_response_time - ah->config.dma_beacon_response_time) - ah->config.additional_swba_backoff) * 1024; REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); - REG_SET_BIT(ah, AR_DMISC(q), - (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << + REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) + | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); REGWRITE_BUFFER_FLUSH(ah); break; case ATH9K_TX_QUEUE_PSPOLL: - REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1); + REG_WRITE(ah, AR_QMISC(q), + REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); break; case ATH9K_TX_QUEUE_UAPSD: - REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); + REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_POST_FR_BKOFF_DIS); break; default: break; } if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { - REG_SET_BIT(ah, AR_DMISC(q), - SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, - AR_D_MISC_ARB_LOCKOUT_CNTRL) | - AR_D_MISC_POST_FR_BKOFF_DIS); + REG_WRITE(ah, AR_DMISC(q), + REG_READ(ah, AR_DMISC(q)) | + SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) | + AR_D_MISC_POST_FR_BKOFF_DIS); } if (AR_SREV_9300_20_OR_LATER(ah)) @@ -713,6 +754,7 @@ EXPORT_SYMBOL(ath9k_hw_abortpcurecv); bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) { #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ +#define AH_RX_TIME_QUANTUM 100 /* usec */ struct ath_common *common = ath9k_hw_common(ah); u32 mac_status, last_mac_status = 0; int i; @@ -755,6 +797,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) return true; } +#undef AH_RX_TIME_QUANTUM #undef AH_RX_STOP_DMA_TIMEOUT } EXPORT_SYMBOL(ath9k_hw_stopdmarecv); @@ -812,14 +855,10 @@ EXPORT_SYMBOL(ath9k_hw_disable_interrupts); void ath9k_hw_enable_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - u32 sync_default = AR_INTR_SYNC_DEFAULT; if (!(ah->imask & ATH9K_INT_GLOBAL)) return; - if (AR_SREV_9340(ah)) - sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; - ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_ENABLE); if (!AR_SREV_9100(ah)) { @@ -828,8 +867,10 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); - REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_DEFAULT); } ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); @@ -885,9 +926,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) mask |= AR_IMR_GENTMR; } - if (ints & ATH9K_INT_GENTIMER) - mask |= AR_IMR_GENTMR; - if (ints & (ATH9K_INT_BMISC)) { mask |= AR_IMR_BCNMISC; if (ints & ATH9K_INT_TIM) diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.h b/trunk/drivers/net/wireless/ath/ath9k/mac.h index b60c130917f7..c2a59386fb9c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.h @@ -239,6 +239,7 @@ struct ath_desc { void *ds_vdata; } __packed __aligned(4); +#define ATH9K_TXDESC_CLRDMASK 0x0001 #define ATH9K_TXDESC_NOACK 0x0002 #define ATH9K_TXDESC_RTSENA 0x0004 #define ATH9K_TXDESC_CTSENA 0x0008 diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index c3dbf2661a3f..17d04ff8d678 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -299,7 +299,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { if (sc->sc_flags & SC_OP_BEACONS) - ath_set_beacon(sc); + ath_beacon_config(sc, NULL); ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); ath_start_ani(common); @@ -624,43 +624,6 @@ void ath_hw_check(struct work_struct *work) ath9k_ps_restore(sc); } -static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) -{ - static int count; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - - if (pll_sqsum >= 0x40000) { - count++; - if (count == 3) { - /* Rx is hung for more than 500ms. Reset it */ - ath_dbg(common, ATH_DBG_RESET, - "Possible RX hang, resetting"); - ath_reset(sc, true); - count = 0; - } - } else - count = 0; -} - -void ath_hw_pll_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - hw_pll_work.work); - u32 pll_sqsum; - - if (AR_SREV_9485(sc->sc_ah)) { - - ath9k_ps_wakeup(sc); - pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); - ath9k_ps_restore(sc); - - ath_hw_pll_rx_hang_check(sc, pll_sqsum); - - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); - } -} - - void ath9k_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; @@ -865,6 +828,48 @@ irqreturn_t ath_isr(int irq, void *dev) #undef SCHED_INTR } +static void ath9k_bss_assoc_info(struct ath_softc *sc, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + + if (bss_conf->assoc) { + ath_dbg(common, ATH_DBG_CONFIG, + "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, common->curbssid); + + /* New association, store aid */ + common->curaid = bss_conf->aid; + ath9k_hw_write_associd(ah); + + /* + * Request a re-configuration of Beacon related timers + * on the receipt of the first Beacon frame (i.e., + * after time sync with the AP). + */ + sc->ps_flags |= PS_BEACON_SYNC; + + /* Configure the beacon */ + ath_beacon_config(sc, vif); + + /* Reset rssi stats */ + sc->last_rssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; + + sc->sc_flags |= SC_OP_ANI_RUN; + ath_start_ani(common); + } else { + ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); + common->curaid = 0; + /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; + del_timer_sync(&common->ani.timer); + } +} + void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; @@ -894,7 +899,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) goto out; } if (sc->sc_flags & SC_OP_BEACONS) - ath_set_beacon(sc); /* restart beacons */ + ath_beacon_config(sc, NULL); /* restart beacons */ /* Re-Enable interrupts */ ath9k_hw_set_interrupts(ah, ah->imask); @@ -1001,7 +1006,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) sc->config.txpowlimit, &sc->curtxpow); if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) - ath_set_beacon(sc); /* restart beacons */ + ath_beacon_config(sc, NULL); /* restart beacons */ ath9k_hw_set_interrupts(ah, ah->imask); @@ -1447,6 +1452,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); + struct ath_vif *avp = (void *)vif->drv_priv; int ret = 0; ath9k_ps_wakeup(sc); @@ -1476,9 +1482,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, } } - if ((ah->opmode == NL80211_IFTYPE_ADHOC) || - ((vif->type == NL80211_IFTYPE_ADHOC) && - sc->nvifs > 0)) { + if ((vif->type == NL80211_IFTYPE_ADHOC) && + sc->nvifs > 0) { ath_err(common, "Cannot create ADHOC interface when other" " interfaces already exist.\n"); ret = -EINVAL; @@ -1488,6 +1493,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ath_dbg(common, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", vif->type); + /* Set the VIF opmode */ + avp->av_opmode = vif->type; + avp->av_bslot = -1; + sc->nvifs++; ath9k_do_vif_add_setup(hw, vif); @@ -1773,63 +1782,23 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_node *an = (struct ath_node *) sta->drv_priv; - struct ieee80211_key_conf ps_key = { }; ath_node_attach(sc, sta); - an->ps_key = ath_key_config(common, vif, sta, &ps_key); return 0; } -static void ath9k_del_ps_key(struct ath_softc *sc, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_node *an = (struct ath_node *) sta->drv_priv; - struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; - - if (!an->ps_key) - return; - - ath_key_delete(common, &ps_key); -} - static int ath9k_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; - ath9k_del_ps_key(sc, vif, sta); ath_node_detach(sc, sta); return 0; } -static void ath9k_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct ath_softc *sc = hw->priv; - struct ath_node *an = (struct ath_node *) sta->drv_priv; - - switch (cmd) { - case STA_NOTIFY_SLEEP: - an->sleeping = true; - if (ath_tx_aggr_sleep(sc, an)) - ieee80211_sta_set_tim(sta); - break; - case STA_NOTIFY_AWAKE: - an->sleeping = false; - ath_tx_aggr_wakeup(sc, an); - break; - } -} - static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -1886,29 +1855,12 @@ static int ath9k_set_key(struct ieee80211_hw *hw, if (ath9k_modparam_nohwcrypt) return -ENOSPC; - if (vif->type == NL80211_IFTYPE_ADHOC && - (key->cipher == WLAN_CIPHER_SUITE_TKIP || - key->cipher == WLAN_CIPHER_SUITE_CCMP) && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* - * For now, disable hw crypto for the RSN IBSS group keys. This - * could be optimized in the future to use a modified key cache - * design to support per-STA RX GTK, but until that gets - * implemented, use of software crypto for group addressed - * frames is a acceptable to allow RSN IBSS to be used. - */ - return -EOPNOTSUPP; - } - mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); switch (cmd) { case SET_KEY: - if (sta) - ath9k_del_ps_key(sc, vif, sta); - ret = ath_key_config(common, vif, sta, key); if (ret >= 0) { key->hw_key_idx = ret; @@ -1934,92 +1886,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw, return ret; } -static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath_softc *sc = data; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct ath_vif *avp = (void *)vif->drv_priv; - - switch (sc->sc_ah->opmode) { - case NL80211_IFTYPE_ADHOC: - /* There can be only one vif available */ - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - common->curaid = bss_conf->aid; - ath9k_hw_write_associd(sc->sc_ah); - /* configure beacon */ - if (bss_conf->enable_beacon) - ath_beacon_config(sc, vif); - break; - case NL80211_IFTYPE_STATION: - /* - * Skip iteration if primary station vif's bss info - * was not changed - */ - if (sc->sc_flags & SC_OP_PRIM_STA_VIF) - break; - - if (bss_conf->assoc) { - sc->sc_flags |= SC_OP_PRIM_STA_VIF; - avp->primary_sta_vif = true; - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - common->curaid = bss_conf->aid; - ath9k_hw_write_associd(sc->sc_ah); - ath_dbg(common, ATH_DBG_CONFIG, - "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, common->curbssid); - ath_beacon_config(sc, vif); - /* - * Request a re-configuration of Beacon related timers - * on the receipt of the first Beacon frame (i.e., - * after time sync with the AP). - */ - sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; - /* Reset rssi stats */ - sc->last_rssi = ATH_RSSI_DUMMY_MARKER; - sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; - - sc->sc_flags |= SC_OP_ANI_RUN; - ath_start_ani(common); - } - break; - default: - break; - } -} - -static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct ath_vif *avp = (void *)vif->drv_priv; - - /* Reconfigure bss info */ - if (avp->primary_sta_vif && !bss_conf->assoc) { - ath_dbg(common, ATH_DBG_CONFIG, - "Bss Info DISASSOC %d, bssid %pM\n", - common->curaid, common->curbssid); - sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); - avp->primary_sta_vif = false; - memset(common->curbssid, 0, ETH_ALEN); - common->curaid = 0; - } - - ieee80211_iterate_active_interfaces_atomic( - sc->hw, ath9k_bss_iter, sc); - - /* - * None of station vifs are associated. - * Clear bssid & aid - */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && - !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { - ath9k_hw_write_associd(sc->sc_ah); - /* Stop ANI */ - sc->sc_flags &= ~SC_OP_ANI_RUN; - del_timer_sync(&common->ani.timer); - } -} static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2027,6 +1893,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct ath_softc *sc = hw->priv; + struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath_vif *avp = (void *)vif->drv_priv; @@ -2037,13 +1904,20 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); if (changed & BSS_CHANGED_BSSID) { - ath9k_config_bss(sc, vif); + /* Set BSSID */ + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); + common->curaid = 0; + ath9k_hw_write_associd(ah); /* Set aggregation protection mode parameters */ sc->config.ath_aggr_prot = 0; ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", common->curbssid, common->curaid); + + /* need to reconfigure the beacon */ + sc->sc_flags &= ~SC_OP_BEACONS ; } /* Enable transmission of beacons (AP, IBSS, MESH) */ @@ -2084,6 +1958,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BEACON_INT) { + cur_conf->beacon_interval = bss_conf->beacon_int; /* * In case of AP mode, the HW TSF has to be reset * when the beacon interval changes. @@ -2095,8 +1970,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, if (!error) ath_beacon_config(sc, vif); ath9k_set_beaconing_status(sc, true); - } else + } else { ath_beacon_config(sc, vif); + } } if (changed & BSS_CHANGED_ERP_PREAMBLE) { @@ -2118,6 +1994,12 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; } + if (changed & BSS_CHANGED_ASSOC) { + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + bss_conf->assoc); + ath9k_bss_assoc_info(sc, hw, vif, bss_conf); + } + mutex_unlock(&sc->mutex); ath9k_ps_restore(sc); } @@ -2262,7 +2144,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) int timeout = 200; /* ms */ int i, j; + ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); + cancel_delayed_work_sync(&sc->tx_complete_work); if (drop) @@ -2285,30 +2169,15 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) goto out; } - ath9k_ps_wakeup(sc); if (!ath_drain_all_txq(sc, false)) ath_reset(sc, false); - ath9k_ps_restore(sc); + ieee80211_wake_queues(hw); out: ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); mutex_unlock(&sc->mutex); -} - -static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) -{ - struct ath_softc *sc = hw->priv; - int i; - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (!ATH_TXQ_SETUP(sc, i)) - continue; - - if (ath9k_has_pending_frames(sc, &sc->tx.txq[i])) - return true; - } - return false; + ath9k_ps_restore(sc); } struct ieee80211_ops ath9k_ops = { @@ -2322,7 +2191,6 @@ struct ieee80211_ops ath9k_ops = { .configure_filter = ath9k_configure_filter, .sta_add = ath9k_sta_add, .sta_remove = ath9k_sta_remove, - .sta_notify = ath9k_sta_notify, .conf_tx = ath9k_conf_tx, .bss_info_changed = ath9k_bss_info_changed, .set_key = ath9k_set_key, @@ -2334,5 +2202,4 @@ struct ieee80211_ops ath9k_ops = { .rfkill_poll = ath9k_rfkill_poll_state, .set_coverage_class = ath9k_set_coverage_class, .flush = ath9k_flush, - .tx_frames_pending = ath9k_tx_frames_pending, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/phy.h b/trunk/drivers/net/wireless/ath/ath9k/phy.h index 9441bf8ca2fd..5e3d7496986e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/phy.h @@ -19,6 +19,7 @@ #define CHANSEL_DIV 15 #define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) +#define CHANSEL_2G_9485(_freq) ((((_freq) * 0x10000) - 215) / CHANSEL_DIV) #define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) #define AR_PHY_BASE 0x9800 @@ -37,15 +38,26 @@ #define AR_PHY_CLC_Q0 0x0000ffd0 #define AR_PHY_CLC_Q0_S 5 +#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ + int r; \ + for (r = 0; r < ((iniarray)->ia_rows); r++) { \ + REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ + DO_DELAY(regWr); \ + } \ + } while (0) + #define ANTSWAP_AB 0x0001 #define REDUCE_CHAIN_0 0x00000050 #define REDUCE_CHAIN_1 0x00000051 #define AR_PHY_CHIP_ID 0x9818 +#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ + int i; \ + for (i = 0; i < (_iniarray)->ia_rows; i++) \ + (_bank)[i] = INI_RA((_iniarray), i, _col);; \ + } while (0) + #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 -#define AR_PHY_PLL_CONTROL 0x16180 -#define AR_PHY_PLL_MODE 0x16184 - #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c index b877d9639bdc..a3241cd089b1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.c +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c @@ -854,13 +854,14 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, ath_rc_rate_set_rtscts(sc, rate_table, tx_info); } -static void ath_rc_update_per(struct ath_softc *sc, +static bool ath_rc_update_per(struct ath_softc *sc, const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_info *tx_info, int tx_rate, int xretries, int retries, u32 now_msec) { + bool state_change = false; int count, n_bad_frames; u8 last_per; static const u32 nretry_to_per_lookup[10] = { @@ -991,6 +992,8 @@ static void ath_rc_update_per(struct ath_softc *sc, } } + + return state_change; } static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, @@ -1014,6 +1017,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, u32 now_msec = jiffies_to_msecs(jiffies); int rate; u8 last_per; + bool state_change = false; const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; int size = ath_rc_priv->rate_table_size; @@ -1023,9 +1027,9 @@ static void ath_rc_update_ht(struct ath_softc *sc, last_per = ath_rc_priv->per[tx_rate]; /* Update PER first */ - ath_rc_update_per(sc, rate_table, ath_rc_priv, - tx_info, tx_rate, xretries, - retries, now_msec); + state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, + tx_info, tx_rate, xretries, + retries, now_msec); /* * If this rate looks bad (high PER) then stop using it for @@ -1088,7 +1092,8 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, if (!(rate->flags & IEEE80211_TX_RC_MCS)) return rate->idx; - while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { + while (rate->idx > mcs_rix_off[i] && + i < ARRAY_SIZE(mcs_rix_off)) { rix++; i++; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index c5b7cbe59bfa..b29c80def35e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -75,6 +75,7 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) *sc->rx.rxlink = bf->bf_daddr; sc->rx.rxlink = &ds->ds_link; + ath9k_hw_rxena(ah); } static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) @@ -425,7 +426,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc) else rfilt |= ATH9K_RX_FILTER_BEACON; - if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || + if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) || + AR_SREV_9285_12_OR_LATER(sc->sc_ah)) && + (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && (sc->rx.rxfilter & FIF_PSPOLL)) rfilt |= ATH9K_RX_FILTER_PSPOLL; @@ -571,7 +574,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) sc->ps_flags &= ~PS_BEACON_SYNC; ath_dbg(common, ATH_DBG_PS, "Reconfigure Beacon timers based on timestamp from the AP\n"); - ath_set_beacon(sc); + ath_beacon_config(sc, NULL); } if (ath_beacon_dtim_pending_cab(skb)) { @@ -1339,7 +1342,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) struct ath_hw_antcomb_conf div_ant_conf; struct ath_ant_comb *antcomb = &sc->ant_comb; int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; - int curr_main_set; + int curr_main_set, curr_bias; int main_rssi = rs->rs_rssi_ctl0; int alt_rssi = rs->rs_rssi_ctl1; int rx_ant_conf, main_ant_conf; @@ -1393,6 +1396,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); curr_alt_set = div_ant_conf.alt_lna_conf; curr_main_set = div_ant_conf.main_lna_conf; + curr_bias = div_ant_conf.fast_div_bias; antcomb->count++; @@ -1742,7 +1746,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA)) || - ath9k_check_auto_sleep(sc)) + unlikely(ath9k_check_auto_sleep(sc))) ath_rx_ps(sc, skb); spin_unlock_irqrestore(&sc->sc_pm_lock, flags); @@ -1763,7 +1767,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) } else { list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); - ath9k_hw_rxena(ah); } } while (1); diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 456f3ec20fef..8fa8acfde62e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -693,7 +693,7 @@ #define AR_RC_APB 0x00000002 #define AR_RC_HOSTIF 0x00000100 -#define AR_WA (AR_SREV_9340(ah) ? 0x40c4 : 0x4004) +#define AR_WA 0x4004 #define AR_WA_BIT6 (1 << 6) #define AR_WA_BIT7 (1 << 7) #define AR_WA_BIT23 (1 << 23) @@ -712,7 +712,7 @@ #define AR_PM_STATE 0x4008 #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 -#define AR_HOST_TIMEOUT (AR_SREV_9340(ah) ? 0x4008 : 0x4018) +#define AR_HOST_TIMEOUT 0x4018 #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF #define AR_HOST_TIMEOUT_APB_CNTR_S 0 #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 @@ -742,8 +742,7 @@ #define EEPROM_PROTECT_WP_1024_2047 0x8000 #define AR_SREV \ - ((AR_SREV_9100(ah)) ? 0x0600 : (AR_SREV_9340(ah) \ - ? 0x400c : 0x4020)) + ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) #define AR_SREV_ID \ ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) @@ -791,7 +790,6 @@ #define AR_SREV_VERSION_9485 0x240 #define AR_SREV_REVISION_9485_10 0 #define AR_SREV_REVISION_9485_11 1 -#define AR_SREV_VERSION_9340 0x300 #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -860,7 +858,9 @@ #define AR_SREV_9300(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) #define AR_SREV_9300_20_OR_LATER(_ah) \ - ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) #define AR_SREV_9485(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) @@ -870,11 +870,6 @@ #define AR_SREV_9485_11(_ah) \ (AR_SREV_9485(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) -#define AR_SREV_9485_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) - -#define AR_SREV_9340(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340)) #define AR_SREV_9285E_20(_ah) \ (AR_SREV_9285_12_OR_LATER(_ah) && \ @@ -917,11 +912,11 @@ enum ath_usb_dev { #define AR_INTR_SPURIOUS 0xFFFFFFFF -#define AR_INTR_SYNC_CAUSE (AR_SREV_9340(ah) ? 0x4010 : 0x4028) -#define AR_INTR_SYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4010 : 0x4028) +#define AR_INTR_SYNC_CAUSE_CLR 0x4028 +#define AR_INTR_SYNC_CAUSE 0x4028 -#define AR_INTR_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4014 : 0x402c) +#define AR_INTR_SYNC_ENABLE 0x402c #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 #define AR_INTR_SYNC_ENABLE_GPIO_S 18 @@ -961,24 +956,24 @@ enum { }; -#define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) +#define AR_INTR_ASYNC_MASK 0x4030 #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 #define AR_INTR_ASYNC_MASK_GPIO_S 18 -#define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) +#define AR_INTR_SYNC_MASK 0x4034 #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 #define AR_INTR_SYNC_MASK_GPIO_S 18 -#define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) -#define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) +#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 +#define AR_INTR_ASYNC_CAUSE 0x4038 -#define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) +#define AR_INTR_ASYNC_ENABLE 0x403c #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 #define AR_PCIE_SERDES 0x4040 #define AR_PCIE_SERDES2 0x4044 -#define AR_PCIE_PM_CTRL (AR_SREV_9340(ah) ? 0x4004 : 0x4014) +#define AR_PCIE_PM_CTRL 0x4014 #define AR_PCIE_PM_CTRL_ENA 0x00080000 #define AR_NUM_GPIO 14 @@ -989,7 +984,7 @@ enum { #define AR9300_NUM_GPIO 17 #define AR7010_NUM_GPIO 16 -#define AR_GPIO_IN_OUT (AR_SREV_9340(ah) ? 0x4028 : 0x4048) +#define AR_GPIO_IN_OUT 0x4048 #define AR_GPIO_IN_VAL 0x0FFFC000 #define AR_GPIO_IN_VAL_S 14 #define AR928X_GPIO_IN_VAL 0x000FFC00 @@ -1003,12 +998,11 @@ enum { #define AR7010_GPIO_IN_VAL 0x0000FFFF #define AR7010_GPIO_IN_VAL_S 0 -#define AR_GPIO_IN (AR_SREV_9340(ah) ? 0x402c : 0x404c) +#define AR_GPIO_IN 0x404c #define AR9300_GPIO_IN_VAL 0x0001FFFF #define AR9300_GPIO_IN_VAL_S 0 -#define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)) +#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) #define AR_GPIO_OE_OUT_DRV 0x3 #define AR_GPIO_OE_OUT_DRV_NO 0x0 #define AR_GPIO_OE_OUT_DRV_LOW 0x1 @@ -1030,13 +1024,11 @@ enum { #define AR7010_GPIO_INT_MASK 0x52024 #define AR7010_GPIO_FUNCTION 0x52028 -#define AR_GPIO_INTR_POL (AR_SREV_9340(ah) ? 0x4038 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)) +#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) #define AR_GPIO_INTR_POL_VAL 0x0001FFFF #define AR_GPIO_INTR_POL_VAL_S 0 -#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9340(ah) ? 0x403c : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054)) +#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054) #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 @@ -1054,15 +1046,13 @@ enum { #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 #define AR_GPIO_JTAG_DISABLE 0x00020000 -#define AR_GPIO_INPUT_MUX1 (AR_SREV_9340(ah) ? 0x4040 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058)) +#define AR_GPIO_INPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058) #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 -#define AR_GPIO_INPUT_MUX2 (AR_SREV_9340(ah) ? 0x4044 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c)) +#define AR_GPIO_INPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c) #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f #define AR_GPIO_INPUT_MUX2_CLK25_S 0 #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 @@ -1070,18 +1060,13 @@ enum { #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 -#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9340(ah) ? 0x4048 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060)) -#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9340(ah) ? 0x404c : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064)) -#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9340(ah) ? 0x4050 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068)) +#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060) +#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064) +#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068) -#define AR_INPUT_STATE (AR_SREV_9340(ah) ? 0x4054 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c)) +#define AR_INPUT_STATE (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c) -#define AR_EEPROM_STATUS_DATA (AR_SREV_9340(ah) ? 0x40c8 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c)) +#define AR_EEPROM_STATUS_DATA (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c) #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff #define AR_EEPROM_STATUS_DATA_VAL_S 0 #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 @@ -1089,51 +1074,28 @@ enum { #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 -#define AR_OBS (AR_SREV_9340(ah) ? 0x405c : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080)) +#define AR_OBS (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080) #define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) -#define AR_PCIE_MSI (AR_SREV_9340(ah) ? 0x40d8 : \ - (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094)) +#define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) #define AR_PCIE_MSI_ENABLE 0x00000001 -#define AR_INTR_PRIO_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4088 : 0x40c4) -#define AR_INTR_PRIO_ASYNC_MASK (AR_SREV_9340(ah) ? 0x408c : 0x40c8) -#define AR_INTR_PRIO_SYNC_MASK (AR_SREV_9340(ah) ? 0x4090 : 0x40cc) -#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) +#define AR_INTR_PRIO_SYNC_ENABLE 0x40c4 +#define AR_INTR_PRIO_ASYNC_MASK 0x40c8 +#define AR_INTR_PRIO_SYNC_MASK 0x40cc +#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 #define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_MPSD 0x00800000 - -#define AR_CH0_BB_DPLL1 0x16180 -#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000 -#define AR_CH0_BB_DPLL1_REFDIV_S 27 -#define AR_CH0_BB_DPLL1_NINI 0x07FC0000 -#define AR_CH0_BB_DPLL1_NINI_S 18 -#define AR_CH0_BB_DPLL1_NFRAC 0x0003FFFF -#define AR_CH0_BB_DPLL1_NFRAC_S 0 - -#define AR_CH0_BB_DPLL2 0x16184 -#define AR_CH0_BB_DPLL2_LOCAL_PLL 0x40000000 -#define AR_CH0_BB_DPLL2_LOCAL_PLL_S 30 -#define AR_CH0_DPLL2_KI 0x3C000000 -#define AR_CH0_DPLL2_KI_S 26 -#define AR_CH0_DPLL2_KD 0x03F80000 -#define AR_CH0_DPLL2_KD_S 19 -#define AR_CH0_BB_DPLL2_EN_NEGTRIG 0x00040000 -#define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18 -#define AR_CH0_BB_DPLL2_PLL_PWD 0x00010000 -#define AR_CH0_BB_DPLL2_PLL_PWD_S 16 -#define AR_CH0_BB_DPLL2_OUTDIV 0x0000E000 -#define AR_CH0_BB_DPLL2_OUTDIV_S 13 - +#define AR_CH0_BB_DPLL2 0x16184 #define AR_CH0_BB_DPLL3 0x16188 -#define AR_CH0_BB_DPLL3_PHASE_SHIFT 0x3F800000 -#define AR_CH0_BB_DPLL3_PHASE_SHIFT_S 23 - #define AR_CH0_DDR_DPLL2 0x16244 #define AR_CH0_DDR_DPLL3 0x16248 +#define AR_CH0_DPLL2_KD 0x03F80000 +#define AR_CH0_DPLL2_KD_S 19 +#define AR_CH0_DPLL2_KI 0x3C000000 +#define AR_CH0_DPLL2_KI_S 26 #define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 #define AR_CH0_DPLL3_PHASE_SHIFT_S 23 #define AR_PHY_CCA_NOM_VAL_2GHZ -118 @@ -1182,7 +1144,6 @@ enum { #define AR_RTC_PLL_REFDIV_5 0x000000c0 #define AR_RTC_PLL_CLKSEL 0x00000300 #define AR_RTC_PLL_CLKSEL_S 8 -#define AR_RTC_PLL_BYPASS 0x00010000 #define PLL3 0x16188 #define PLL3_DO_MEAS_MASK 0x40000000 @@ -1229,8 +1190,7 @@ enum { /* RTC_DERIVED_* - only for AR9100 */ -#define AR_RTC_DERIVED_CLK \ - (AR_SREV_9100(ah) ? (AR_RTC_BASE + 0x0038) : 0x7038) +#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) #define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe #define AR_RTC_DERIVED_CLK_PERIOD_S 1 @@ -1436,7 +1396,6 @@ enum { #define AR_STA_ID1_PCF 0x00100000 #define AR_STA_ID1_USE_DEFANT 0x00200000 #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 -#define AR_STA_ID1_AR9100_BA_FIX 0x00400000 #define AR_STA_ID1_RTS_USE_DEF 0x00800000 #define AR_STA_ID1_ACKCTS_6MB 0x01000000 #define AR_STA_ID1_BASE_RATE_11B 0x02000000 @@ -1709,22 +1668,6 @@ enum { #define AR_BTCOEX_WL_WGHT 0xffff0000 #define AR_BTCOEX_WL_WGHT_S 16 -#define AR_BT_COEX_WL_WEIGHTS0 0x8174 -#define AR_BT_COEX_WL_WEIGHTS1 0x81c4 - -#define AR_BT_COEX_BT_WEIGHTS0 0x83ac -#define AR_BT_COEX_BT_WEIGHTS1 0x83b0 -#define AR_BT_COEX_BT_WEIGHTS2 0x83b4 -#define AR_BT_COEX_BT_WEIGHTS3 0x83b8 - -#define AR9300_BT_WGHT 0xcccc4444 -#define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0 -#define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0 -#define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880 -#define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880 -#define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000 -#define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000 - #define AR_BT_COEX_MODE2 0x817c #define AR_BT_BCN_MISS_THRESH 0x000000ff #define AR_BT_BCN_MISS_THRESH_S 0 diff --git a/trunk/drivers/net/wireless/ath/ath9k/wmi.c b/trunk/drivers/net/wireless/ath/ath9k/wmi.c index f9b1eb4853c4..d3d24904f62f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/wmi.c +++ b/trunk/drivers/net/wireless/ath/ath9k/wmi.c @@ -23,18 +23,20 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_ECHO_CMDID"; case WMI_ACCESS_MEMORY_CMDID: return "WMI_ACCESS_MEMORY_CMDID"; - case WMI_GET_FW_VERSION: - return "WMI_GET_FW_VERSION"; case WMI_DISABLE_INTR_CMDID: return "WMI_DISABLE_INTR_CMDID"; case WMI_ENABLE_INTR_CMDID: return "WMI_ENABLE_INTR_CMDID"; + case WMI_RX_LINK_CMDID: + return "WMI_RX_LINK_CMDID"; case WMI_ATH_INIT_CMDID: return "WMI_ATH_INIT_CMDID"; case WMI_ABORT_TXQ_CMDID: return "WMI_ABORT_TXQ_CMDID"; case WMI_STOP_TX_DMA_CMDID: return "WMI_STOP_TX_DMA_CMDID"; + case WMI_STOP_DMA_RECV_CMDID: + return "WMI_STOP_DMA_RECV_CMDID"; case WMI_ABORT_TX_DMA_CMDID: return "WMI_ABORT_TX_DMA_CMDID"; case WMI_DRAIN_TXQ_CMDID: @@ -49,6 +51,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_FLUSH_RECV_CMDID"; case WMI_SET_MODE_CMDID: return "WMI_SET_MODE_CMDID"; + case WMI_RESET_CMDID: + return "WMI_RESET_CMDID"; case WMI_NODE_CREATE_CMDID: return "WMI_NODE_CREATE_CMDID"; case WMI_NODE_REMOVE_CMDID: @@ -57,6 +61,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_VAP_REMOVE_CMDID"; case WMI_VAP_CREATE_CMDID: return "WMI_VAP_CREATE_CMDID"; + case WMI_BEACON_UPDATE_CMDID: + return "WMI_BEACON_UPDATE_CMDID"; case WMI_REG_READ_CMDID: return "WMI_REG_READ_CMDID"; case WMI_REG_WRITE_CMDID: @@ -65,22 +71,22 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) return "WMI_RC_STATE_CHANGE_CMDID"; case WMI_RC_RATE_UPDATE_CMDID: return "WMI_RC_RATE_UPDATE_CMDID"; + case WMI_DEBUG_INFO_CMDID: + return "WMI_DEBUG_INFO_CMDID"; + case WMI_HOST_ATTACH: + return "WMI_HOST_ATTACH"; case WMI_TARGET_IC_UPDATE_CMDID: return "WMI_TARGET_IC_UPDATE_CMDID"; + case WMI_TGT_STATS_CMDID: + return "WMI_TGT_STATS_CMDID"; case WMI_TX_AGGR_ENABLE_CMDID: return "WMI_TX_AGGR_ENABLE_CMDID"; case WMI_TGT_DETACH_CMDID: return "WMI_TGT_DETACH_CMDID"; - case WMI_NODE_UPDATE_CMDID: - return "WMI_NODE_UPDATE_CMDID"; - case WMI_INT_STATS_CMDID: - return "WMI_INT_STATS_CMDID"; - case WMI_TX_STATS_CMDID: - return "WMI_TX_STATS_CMDID"; - case WMI_RX_STATS_CMDID: - return "WMI_RX_STATS_CMDID"; - case WMI_BITRATE_MASK_CMDID: - return "WMI_BITRATE_MASK_CMDID"; + case WMI_TGT_TXQ_ENABLE_CMDID: + return "WMI_TGT_TXQ_ENABLE_CMDID"; + case WMI_AGGR_LIMIT_CMD: + return "WMI_AGGR_LIMIT_CMD"; } return "Bogus"; @@ -96,15 +102,9 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) wmi->drv_priv = priv; wmi->stopped = false; - skb_queue_head_init(&wmi->wmi_event_queue); - spin_lock_init(&wmi->wmi_lock); - spin_lock_init(&wmi->event_lock); mutex_init(&wmi->op_mutex); mutex_init(&wmi->multi_write_mutex); init_completion(&wmi->cmd_wait); - INIT_LIST_HEAD(&wmi->pending_tx_events); - tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, - (unsigned long)wmi); return wmi; } @@ -120,65 +120,11 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) kfree(priv->wmi); } -void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv) +void ath9k_swba_tasklet(unsigned long data) { - unsigned long flags; + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - tasklet_kill(&priv->wmi->wmi_event_tasklet); - spin_lock_irqsave(&priv->wmi->wmi_lock, flags); - __skb_queue_purge(&priv->wmi->wmi_event_queue); - spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); -} - -void ath9k_wmi_event_tasklet(unsigned long data) -{ - struct wmi *wmi = (struct wmi *)data; - struct ath9k_htc_priv *priv = wmi->drv_priv; - struct wmi_cmd_hdr *hdr; - void *wmi_event; - struct wmi_event_swba *swba; - struct sk_buff *skb = NULL; - unsigned long flags; - u16 cmd_id; - - do { - spin_lock_irqsave(&wmi->wmi_lock, flags); - skb = __skb_dequeue(&wmi->wmi_event_queue); - if (!skb) { - spin_unlock_irqrestore(&wmi->wmi_lock, flags); - return; - } - spin_unlock_irqrestore(&wmi->wmi_lock, flags); - - hdr = (struct wmi_cmd_hdr *) skb->data; - cmd_id = be16_to_cpu(hdr->command_id); - wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); - - switch (cmd_id) { - case WMI_SWBA_EVENTID: - swba = (struct wmi_event_swba *) wmi_event; - ath9k_htc_swba(priv, swba); - break; - case WMI_FATAL_EVENTID: - ieee80211_queue_work(wmi->drv_priv->hw, - &wmi->drv_priv->fatal_work); - break; - case WMI_TXSTATUS_EVENTID: - spin_lock_bh(&priv->tx.tx_lock); - if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { - spin_unlock_bh(&priv->tx.tx_lock); - break; - } - spin_unlock_bh(&priv->tx.tx_lock); - - ath9k_htc_txstatus(priv, wmi_event); - break; - default: - break; - } - - kfree_skb(skb); - } while (1); + ath9k_htc_swba(priv, priv->wmi->beacon_pending); } void ath9k_fatal_work(struct work_struct *work) @@ -207,6 +153,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, struct wmi *wmi = (struct wmi *) priv; struct wmi_cmd_hdr *hdr; u16 cmd_id; + void *wmi_event; +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + __be32 txrate; +#endif if (unlikely(wmi->stopped)) goto free_skb; @@ -215,10 +165,26 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, cmd_id = be16_to_cpu(hdr->command_id); if (cmd_id & 0x1000) { - spin_lock(&wmi->wmi_lock); - __skb_queue_tail(&wmi->wmi_event_queue, skb); - spin_unlock(&wmi->wmi_lock); - tasklet_schedule(&wmi->wmi_event_tasklet); + wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + switch (cmd_id) { + case WMI_SWBA_EVENTID: + wmi->beacon_pending = *(u8 *)wmi_event; + tasklet_schedule(&wmi->drv_priv->swba_tasklet); + break; + case WMI_FATAL_EVENTID: + ieee80211_queue_work(wmi->drv_priv->hw, + &wmi->drv_priv->fatal_work); + break; + case WMI_TXRATE_EVENTID: +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; + wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); +#endif + break; + default: + break; + } + kfree_skb(skb); return; } @@ -277,7 +243,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, hdr->command_id = cpu_to_be16(cmd); hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); - return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid); + return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); } int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, diff --git a/trunk/drivers/net/wireless/ath/ath9k/wmi.h b/trunk/drivers/net/wireless/ath/ath9k/wmi.h index 6095eeb6e025..42084277522d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/wmi.h +++ b/trunk/drivers/net/wireless/ath/ath9k/wmi.h @@ -17,6 +17,7 @@ #ifndef WMI_H #define WMI_H + struct wmi_event_txrate { __be32 txrate; struct { @@ -30,65 +31,18 @@ struct wmi_cmd_hdr { __be16 seq_no; } __packed; -struct wmi_fw_version { - __be16 major; - __be16 minor; - -} __packed; - -struct wmi_event_swba { - __be64 tsf; - u8 beacon_pending; -}; - -/* - * 64 - HTC header - WMI header - 1 / txstatus - * And some other hdr. space is also accounted for. - * 12 seems to be the magic number. - */ -#define HTC_MAX_TX_STATUS 12 - -#define ATH9K_HTC_TXSTAT_ACK BIT(0) -#define ATH9K_HTC_TXSTAT_FILT BIT(1) -#define ATH9K_HTC_TXSTAT_RTC_CTS BIT(2) -#define ATH9K_HTC_TXSTAT_MCS BIT(3) -#define ATH9K_HTC_TXSTAT_CW40 BIT(4) -#define ATH9K_HTC_TXSTAT_SGI BIT(5) - -/* - * Legacy rates are indicated as indices. - * HT rates are indicated as dot11 numbers. - * This allows us to resrict the rate field - * to 4 bits. - */ -#define ATH9K_HTC_TXSTAT_RATE 0x0f -#define ATH9K_HTC_TXSTAT_RATE_S 0 - -#define ATH9K_HTC_TXSTAT_EPID 0xf0 -#define ATH9K_HTC_TXSTAT_EPID_S 4 - -struct __wmi_event_txstatus { - u8 cookie; - u8 ts_rate; /* Also holds EP ID */ - u8 ts_flags; -}; - -struct wmi_event_txstatus { - u8 cnt; - struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS]; -} __packed; - enum wmi_cmd_id { WMI_ECHO_CMDID = 0x0001, WMI_ACCESS_MEMORY_CMDID, /* Commands to Target */ - WMI_GET_FW_VERSION, WMI_DISABLE_INTR_CMDID, WMI_ENABLE_INTR_CMDID, + WMI_RX_LINK_CMDID, WMI_ATH_INIT_CMDID, WMI_ABORT_TXQ_CMDID, WMI_STOP_TX_DMA_CMDID, + WMI_STOP_DMA_RECV_CMDID, WMI_ABORT_TX_DMA_CMDID, WMI_DRAIN_TXQ_CMDID, WMI_DRAIN_TXQ_ALL_CMDID, @@ -96,22 +50,24 @@ enum wmi_cmd_id { WMI_STOP_RECV_CMDID, WMI_FLUSH_RECV_CMDID, WMI_SET_MODE_CMDID, + WMI_RESET_CMDID, WMI_NODE_CREATE_CMDID, WMI_NODE_REMOVE_CMDID, WMI_VAP_REMOVE_CMDID, WMI_VAP_CREATE_CMDID, + WMI_BEACON_UPDATE_CMDID, WMI_REG_READ_CMDID, WMI_REG_WRITE_CMDID, WMI_RC_STATE_CHANGE_CMDID, WMI_RC_RATE_UPDATE_CMDID, + WMI_DEBUG_INFO_CMDID, + WMI_HOST_ATTACH, WMI_TARGET_IC_UPDATE_CMDID, + WMI_TGT_STATS_CMDID, WMI_TX_AGGR_ENABLE_CMDID, WMI_TGT_DETACH_CMDID, - WMI_NODE_UPDATE_CMDID, - WMI_INT_STATS_CMDID, - WMI_TX_STATS_CMDID, - WMI_RX_STATS_CMDID, - WMI_BITRATE_MASK_CMDID, + WMI_TGT_TXQ_ENABLE_CMDID, + WMI_AGGR_LIMIT_CMD = 0x0026, }; enum wmi_event_id { @@ -120,8 +76,9 @@ enum wmi_event_id { WMI_FATAL_EVENTID, WMI_TXTO_EVENTID, WMI_BMISS_EVENTID, + WMI_WLAN_TXCOMP_EVENTID, WMI_DELBA_EVENTID, - WMI_TXSTATUS_EVENTID, + WMI_TXRATE_EVENTID, }; #define MAX_CMD_NUMBER 62 @@ -131,12 +88,6 @@ struct register_write { __be32 val; }; -struct ath9k_htc_tx_event { - int count; - struct __wmi_event_txstatus txs; - struct list_head list; -}; - struct wmi { struct ath9k_htc_priv *drv_priv; struct htc_target *htc; @@ -144,16 +95,12 @@ struct wmi { struct mutex op_mutex; struct completion cmd_wait; enum wmi_cmd_id last_cmd_id; - struct sk_buff_head wmi_event_queue; - struct tasklet_struct wmi_event_tasklet; u16 tx_seq_id; u8 *cmd_rsp_buf; u32 cmd_rsp_len; bool stopped; - struct list_head pending_tx_events; - spinlock_t event_lock; - + u8 beacon_pending; spinlock_t wmi_lock; atomic_t mwrite_cnt; @@ -170,9 +117,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, u8 *cmd_buf, u32 cmd_len, u8 *rsp_buf, u32 rsp_len, u32 timeout); -void ath9k_wmi_event_tasklet(unsigned long data); +void ath9k_swba_tasklet(unsigned long data); void ath9k_fatal_work(struct work_struct *work); -void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv); #define WMI_CMD(_wmi_cmd) \ do { \ diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 55960fa70dc6..26734e53b37f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -357,7 +357,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_frame_info *fi; int nframes; u8 tidno; - bool clear_filter; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -442,24 +441,22 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* transmit completion */ acked_cnt++; } else { - if ((tid->state & AGGR_CLEANUP) || !retry) { + if (!(tid->state & AGGR_CLEANUP) && retry) { + if (fi->retries < ATH_MAX_SW_RETRIES) { + ath_tx_set_retry(sc, txq, bf->bf_mpdu); + txpending = 1; + } else { + bf->bf_state.bf_type |= BUF_XRETRY; + txfail = 1; + sendbar = 1; + txfail_cnt++; + } + } else { /* * cleanup in progress, just fail * the un-acked sub-frames */ txfail = 1; - } else if (fi->retries < ATH_MAX_SW_RETRIES) { - if (!(ts->ts_status & ATH9K_TXERR_FILT) || - !an->sleeping) - ath_tx_set_retry(sc, txq, bf->bf_mpdu); - - clear_filter = true; - txpending = 1; - } else { - bf->bf_state.bf_type |= BUF_XRETRY; - txfail = 1; - sendbar = 1; - txfail_cnt++; } } @@ -499,7 +496,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, !txfail, sendbar); } else { /* retry the un-acked ones */ - ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { if (bf->bf_next == NULL && bf_last->bf_stale) { struct ath_buf *tbf; @@ -550,12 +546,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* prepend un-acked frames to the beginning of the pending frame queue */ if (!list_empty(&bf_pending)) { - if (an->sleeping) - ieee80211_sta_set_tim(sta); - spin_lock_bh(&txq->axq_lock); - if (clear_filter) - tid->ac->clear_ps_filter = true; list_splice(&bf_pending, &tid->buf_q); ath_tx_queue_tid(txq, tid); spin_unlock_bh(&txq->axq_lock); @@ -825,11 +816,6 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, bf = list_first_entry(&bf_q, struct ath_buf, list); bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); - if (tid->ac->clear_ps_filter) { - tid->ac->clear_ps_filter = false; - ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); - } - /* if only one frame, send as non-aggregate */ if (bf == bf->bf_lastbf) { fi = get_frame_info(bf->bf_mpdu); @@ -910,67 +896,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ath_tx_flush_tid(sc, txtid); } -bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) -{ - struct ath_atx_tid *tid; - struct ath_atx_ac *ac; - struct ath_txq *txq; - bool buffered = false; - int tidno; - - for (tidno = 0, tid = &an->tid[tidno]; - tidno < WME_NUM_TID; tidno++, tid++) { - - if (!tid->sched) - continue; - - ac = tid->ac; - txq = ac->txq; - - spin_lock_bh(&txq->axq_lock); - - if (!list_empty(&tid->buf_q)) - buffered = true; - - tid->sched = false; - list_del(&tid->list); - - if (ac->sched) { - ac->sched = false; - list_del(&ac->list); - } - - spin_unlock_bh(&txq->axq_lock); - } - - return buffered; -} - -void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) -{ - struct ath_atx_tid *tid; - struct ath_atx_ac *ac; - struct ath_txq *txq; - int tidno; - - for (tidno = 0, tid = &an->tid[tidno]; - tidno < WME_NUM_TID; tidno++, tid++) { - - ac = tid->ac; - txq = ac->txq; - - spin_lock_bh(&txq->axq_lock); - ac->clear_ps_filter = true; - - if (!list_empty(&tid->buf_q) && !tid->paused) { - ath_tx_queue_tid(txq, tid); - ath_txq_schedule(sc, txq); - } - - spin_unlock_bh(&txq->axq_lock); - } -} - void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) { struct ath_atx_tid *txtid; @@ -1526,7 +1451,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr; struct ath_frame_info *fi = get_frame_info(skb); - struct ath_node *an = NULL; + struct ath_node *an; struct ath_atx_tid *tid; enum ath9k_key_type keytype; u16 seqno = 0; @@ -1534,13 +1459,11 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - if (sta) - an = (struct ath_node *) sta->drv_priv; - hdr = (struct ieee80211_hdr *)skb->data; - if (an && ieee80211_is_data_qos(hdr->frame_control) && + if (sta && ieee80211_is_data_qos(hdr->frame_control) && conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { + an = (struct ath_node *) sta->drv_priv; tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; /* @@ -1556,8 +1479,6 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, memset(fi, 0, sizeof(*fi)); if (hw_key) fi->keyix = hw_key->hw_key_idx; - else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) - fi->keyix = an->ps_key; else fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keytype = keytype; @@ -1570,6 +1491,7 @@ static int setup_tx_flags(struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; + flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ flags |= ATH9K_TXDESC_INTREQ; if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) @@ -1832,9 +1754,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, if (txctl->paprd) bf->bf_state.bfs_paprd_timestamp = jiffies; - if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) - ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); - ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); } @@ -2061,7 +1980,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, if (ieee80211_is_data(hdr->frame_control) && (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) && - ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level) + ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) tx_info->status.rates[tx_rateindex].count = hw->max_rate_tries; } @@ -2180,6 +2099,28 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) } } +static void ath_hw_pll_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + hw_pll_work.work); + static int count; + + if (AR_SREV_9485(sc->sc_ah)) { + if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { + count++; + + if (count == 3) { + /* Rx is hung for more than 500ms. Reset it */ + ath_reset(sc, true); + count = 0; + } + } else + count = 0; + + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); + } +} + static void ath_tx_complete_poll_work(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, @@ -2203,6 +2144,33 @@ static void ath_tx_complete_poll_work(struct work_struct *work) } else { txq->axq_tx_inprogress = true; } + } else { + /* If the queue has pending buffers, then it + * should be doing tx work (and have axq_depth). + * Shouldn't get to this state I think..but + * we do. + */ + if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && + (txq->pending_frames > 0 || + !list_empty(&txq->axq_acq) || + txq->stopped)) { + ath_err(ath9k_hw_common(sc->sc_ah), + "txq: %p axq_qnum: %u," + " mac80211_qnum: %i" + " axq_link: %p" + " pending frames: %i" + " axq_acq empty: %i" + " stopped: %i" + " axq_depth: 0 Attempting to" + " restart tx logic.\n", + txq, txq->axq_qnum, + txq->mac80211_qnum, + txq->axq_link, + txq->pending_frames, + list_empty(&txq->axq_acq), + txq->stopped); + ath_txq_schedule(sc, txq); + } } spin_unlock_bh(&txq->axq_lock); } @@ -2374,6 +2342,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) } INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); + INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { error = ath_tx_edma_init(sc); diff --git a/trunk/drivers/net/wireless/ath/carl9170/carl9170.h b/trunk/drivers/net/wireless/ath/carl9170/carl9170.h index beb725d7547f..9cad061cc1d2 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/trunk/drivers/net/wireless/ath/carl9170/carl9170.h @@ -448,8 +448,6 @@ struct carl9170_ba_stats { struct carl9170_sta_info { bool ht_sta; - bool sleeping; - atomic_t pending_frames; unsigned int ampdu_max_len; struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; struct carl9170_ba_stats stats[CARL9170_NUM_TID]; diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index 1638468be5a3..89fe60accf85 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -1193,8 +1193,6 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw, struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; unsigned int i; - atomic_set(&sta_info->pending_frames, 0); - if (sta->ht_cap.ht_supported) { if (sta->ht_cap.ampdu_density > 6) { /* @@ -1469,17 +1467,99 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { + struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; + struct sk_buff *skb, *tmp; + struct sk_buff_head free; + int i; switch (cmd) { case STA_NOTIFY_SLEEP: - sta_info->sleeping = true; - if (atomic_read(&sta_info->pending_frames)) - ieee80211_sta_block_awake(hw, sta, true); + /* + * Since the peer is no longer listening, we have to return + * as many SKBs as possible back to the mac80211 stack. + * It will deal with the retry procedure, once the peer + * has become available again. + * + * NB: Ideally, the driver should return the all frames in + * the correct, ascending order. However, I think that this + * functionality should be implemented in the stack and not + * here... + */ + + __skb_queue_head_init(&free); + + if (sta->ht_cap.ht_supported) { + rcu_read_lock(); + for (i = 0; i < CARL9170_NUM_TID; i++) { + struct carl9170_sta_tid *tid_info; + + tid_info = rcu_dereference(sta_info->agg[i]); + + if (!tid_info) + continue; + + spin_lock_bh(&ar->tx_ampdu_list_lock); + if (tid_info->state > + CARL9170_TID_STATE_SUSPEND) + tid_info->state = + CARL9170_TID_STATE_SUSPEND; + spin_unlock_bh(&ar->tx_ampdu_list_lock); + + spin_lock_bh(&tid_info->lock); + while ((skb = __skb_dequeue(&tid_info->queue))) + __skb_queue_tail(&free, skb); + spin_unlock_bh(&tid_info->lock); + } + rcu_read_unlock(); + } + + for (i = 0; i < ar->hw->queues; i++) { + spin_lock_bh(&ar->tx_pending[i].lock); + skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) { + struct _carl9170_tx_superframe *super; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info; + + super = (void *) skb->data; + hdr = (void *) super->frame_data; + + if (compare_ether_addr(hdr->addr1, sta->addr)) + continue; + + __skb_unlink(skb, &ar->tx_pending[i]); + + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + atomic_dec(&ar->tx_ampdu_upload); + + carl9170_tx_status(ar, skb, false); + } + spin_unlock_bh(&ar->tx_pending[i].lock); + } + + while ((skb = __skb_dequeue(&free))) + carl9170_tx_status(ar, skb, false); + break; case STA_NOTIFY_AWAKE: - sta_info->sleeping = false; + if (!sta->ht_cap.ht_supported) + return; + + rcu_read_lock(); + for (i = 0; i < CARL9170_NUM_TID; i++) { + struct carl9170_sta_tid *tid_info; + + tid_info = rcu_dereference(sta_info->agg[i]); + + if (!tid_info) + continue; + + if ((tid_info->state == CARL9170_TID_STATE_SUSPEND)) + tid_info->state = CARL9170_TID_STATE_IDLE; + } + rcu_read_unlock(); break; } } diff --git a/trunk/drivers/net/wireless/ath/carl9170/tx.c b/trunk/drivers/net/wireless/ath/carl9170/tx.c index bf2eff9dd582..cb70ed7ec5cc 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/tx.c +++ b/trunk/drivers/net/wireless/ath/carl9170/tx.c @@ -104,56 +104,6 @@ static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb) spin_unlock_bh(&ar->tx_stats_lock); } -/* needs rcu_read_lock */ -static struct ieee80211_sta *__carl9170_get_tx_sta(struct ar9170 *ar, - struct sk_buff *skb) -{ - struct _carl9170_tx_superframe *super = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) super->frame_data; - struct ieee80211_vif *vif; - unsigned int vif_id; - - vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> - CARL9170_TX_SUPER_MISC_VIF_ID_S; - - if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) - return NULL; - - vif = rcu_dereference(ar->vif_priv[vif_id].vif); - if (unlikely(!vif)) - return NULL; - - /* - * Normally we should use wrappers like ieee80211_get_DA to get - * the correct peer ieee80211_sta. - * - * But there is a problem with indirect traffic (broadcasts, or - * data which is designated for other stations) in station mode. - * The frame will be directed to the AP for distribution and not - * to the actual destination. - */ - - return ieee80211_find_sta(vif, hdr->addr1); -} - -static void carl9170_tx_ps_unblock(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_sta *sta; - struct carl9170_sta_info *sta_info; - - rcu_read_lock(); - sta = __carl9170_get_tx_sta(ar, skb); - if (unlikely(!sta)) - goto out_rcu; - - sta_info = (struct carl9170_sta_info *) sta->drv_priv; - if (atomic_dec_return(&sta_info->pending_frames) == 0) - ieee80211_sta_block_awake(ar->hw, sta, false); - -out_rcu: - rcu_read_unlock(); -} - static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) { struct ieee80211_tx_info *txinfo; @@ -185,7 +135,6 @@ static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) } spin_unlock_bh(&ar->tx_stats_lock); - if (atomic_dec_and_test(&ar->tx_total_queued)) complete(&ar->tx_flush); } @@ -380,10 +329,13 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, { struct _carl9170_tx_superframe *super = (void *) skb->data; struct ieee80211_hdr *hdr = (void *) super->frame_data; + struct ieee80211_tx_info *tx_info; struct carl9170_tx_info *ar_info; - struct ieee80211_sta *sta; struct carl9170_sta_info *sta_info; + struct ieee80211_sta *sta; struct carl9170_sta_tid *tid_info; + struct ieee80211_vif *vif; + unsigned int vif_id; u8 tid; if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || @@ -391,10 +343,30 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) return; - ar_info = (void *) txinfo->rate_driver_data; + tx_info = IEEE80211_SKB_CB(skb); + ar_info = (void *) tx_info->rate_driver_data; + + vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> + CARL9170_TX_SUPER_MISC_VIF_ID_S; + + if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) + return; rcu_read_lock(); - sta = __carl9170_get_tx_sta(ar, skb); + vif = rcu_dereference(ar->vif_priv[vif_id].vif); + if (unlikely(!vif)) + goto out_rcu; + + /* + * Normally we should use wrappers like ieee80211_get_DA to get + * the correct peer ieee80211_sta. + * + * But there is a problem with indirect traffic (broadcasts, or + * data which is designated for other stations) in station mode. + * The frame will be directed to the AP for distribution and not + * to the actual destination. + */ + sta = ieee80211_find_sta(vif, hdr->addr1); if (unlikely(!sta)) goto out_rcu; @@ -455,7 +427,6 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) carl9170_tx_status_process_ampdu(ar, skb, txinfo); - carl9170_tx_ps_unblock(ar, skb); carl9170_tx_put_skb(skb); } @@ -569,7 +540,11 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) struct sk_buff *skb; struct ieee80211_tx_info *txinfo; struct carl9170_tx_info *arinfo; + struct _carl9170_tx_superframe *super; struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct ieee80211_hdr *hdr; + unsigned int vif_id; rcu_read_lock(); list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { @@ -587,7 +562,20 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) goto unlock; - sta = __carl9170_get_tx_sta(ar, skb); + super = (void *) skb->data; + hdr = (void *) super->frame_data; + + vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> + CARL9170_TX_SUPER_MISC_VIF_ID_S; + + if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC)) + goto unlock; + + vif = rcu_dereference(ar->vif_priv[vif_id].vif); + if (WARN_ON(!vif)) + goto unlock; + + sta = ieee80211_find_sta(vif, hdr->addr1); if (WARN_ON(!sta)) goto unlock; @@ -1211,6 +1199,15 @@ static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar, arinfo = (void *) info->rate_driver_data; arinfo->timeout = jiffies; + + /* + * increase ref count to "2". + * Ref counting is the easiest way to solve the race between + * the the urb's completion routine: carl9170_tx_callback and + * wlan tx status functions: carl9170_tx_status/janitor. + */ + carl9170_tx_get_skb(skb); + return skb; err_unlock: @@ -1231,36 +1228,6 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb) __carl9170_tx_process_status(ar, super->s.cookie, q); } -static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_sta *sta; - struct carl9170_sta_info *sta_info; - - rcu_read_lock(); - sta = __carl9170_get_tx_sta(ar, skb); - if (!sta) - goto out_rcu; - - sta_info = (void *) sta->drv_priv; - if (unlikely(sta_info->sleeping)) { - struct ieee80211_tx_info *tx_info; - - rcu_read_unlock(); - - tx_info = IEEE80211_SKB_CB(skb); - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) - atomic_dec(&ar->tx_ampdu_upload); - - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - carl9170_tx_status(ar, skb, false); - return true; - } - -out_rcu: - rcu_read_unlock(); - return false; -} - static void carl9170_tx(struct ar9170 *ar) { struct sk_buff *skb; @@ -1280,9 +1247,6 @@ static void carl9170_tx(struct ar9170 *ar) if (unlikely(!skb)) break; - if (unlikely(carl9170_tx_ps_drop(ar, skb))) - continue; - atomic_inc(&ar->tx_total_pending); q = __carl9170_get_queue(ar, i); @@ -1292,16 +1256,6 @@ static void carl9170_tx(struct ar9170 *ar) */ skb_queue_tail(&ar->tx_status[q], skb); - /* - * increase ref count to "2". - * Ref counting is the easiest way to solve the - * race between the urb's completion routine: - * carl9170_tx_callback - * and wlan tx status functions: - * carl9170_tx_status/janitor. - */ - carl9170_tx_get_skb(skb); - carl9170_usb_tx(ar, skb); schedule_garbagecollector = true; } @@ -1414,11 +1368,6 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * all ressouces which are associated with the frame. */ - if (sta) { - struct carl9170_sta_info *stai = (void *) sta->drv_priv; - atomic_inc(&stai->pending_frames); - } - if (info->flags & IEEE80211_TX_CTL_AMPDU) { run = carl9170_tx_ampdu_queue(ar, sta, skb); if (run) diff --git a/trunk/drivers/net/wireless/ath/key.c b/trunk/drivers/net/wireless/ath/key.c index a61ef3d6d89c..37b8e115375a 100644 --- a/trunk/drivers/net/wireless/ath/key.c +++ b/trunk/drivers/net/wireless/ath/key.c @@ -23,14 +23,6 @@ #define REG_READ (common->ops->read) #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) -#define ENABLE_REGWRITE_BUFFER(_ah) \ - if (common->ops->enable_write_buffer) \ - common->ops->enable_write_buffer((_ah)); - -#define REGWRITE_BUFFER_FLUSH(_ah) \ - if (common->ops->write_flush) \ - common->ops->write_flush((_ah)); - #define IEEE80211_WEP_NKID 4 /* number of key ids */ @@ -50,8 +42,6 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); - ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); @@ -76,8 +66,6 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) } - REGWRITE_BUFFER_FLUSH(ah); - return true; } EXPORT_SYMBOL(ath_hw_keyreset); @@ -116,13 +104,9 @@ static bool ath_hw_keysetmac(struct ath_common *common, } else { macLo = macHi = 0; } - ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); - REGWRITE_BUFFER_FLUSH(ah); - return true; } @@ -239,8 +223,6 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; mic4 = get_unaligned_le32(k->kv_txmic + 4); - ENABLE_REGWRITE_BUFFER(ah); - /* Write RX[31:0] and TX[31:16] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); @@ -254,8 +236,6 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); - REGWRITE_BUFFER_FLUSH(ah); - } else { /* * TKIP uses four key cache entries (two for group @@ -278,8 +258,6 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, mic0 = get_unaligned_le32(k->kv_mic + 0); mic2 = get_unaligned_le32(k->kv_mic + 4); - ENABLE_REGWRITE_BUFFER(ah); - /* Write MIC key[31:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); @@ -292,12 +270,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR); - - REGWRITE_BUFFER_FLUSH(ah); } - ENABLE_REGWRITE_BUFFER(ah); - /* MAC address registers are reserved for the MIC entry */ REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); @@ -309,11 +283,7 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); - - REGWRITE_BUFFER_FLUSH(ah); } else { - ENABLE_REGWRITE_BUFFER(ah); - /* Write key[47:0] */ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); @@ -326,8 +296,6 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); - REGWRITE_BUFFER_FLUSH(ah); - /* Write MAC address for the entry */ (void) ath_hw_keysetmac(common, entry, mac); } @@ -483,9 +451,6 @@ int ath_key_config(struct ath_common *common, memset(&hk, 0, sizeof(hk)); switch (key->cipher) { - case 0: - hk.kv_type = ATH_CIPHER_CLR; - break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: hk.kv_type = ATH_CIPHER_WEP; @@ -501,8 +466,7 @@ int ath_key_config(struct ath_common *common, } hk.kv_len = key->keylen; - if (key->keylen) - memcpy(hk.kv_val, key->key, key->keylen); + memcpy(hk.kv_val, key->key, key->keylen); if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { switch (vif->type) { diff --git a/trunk/drivers/net/wireless/ath/regd.c b/trunk/drivers/net/wireless/ath/regd.c index 02b896208b1a..f828f294ba89 100644 --- a/trunk/drivers/net/wireless/ath/regd.c +++ b/trunk/drivers/net/wireless/ath/regd.c @@ -97,8 +97,8 @@ static const struct ieee80211_regdomain ath_world_regdom_66_69 = { } }; -/* Can be used by 0x67, 0x68, 0x6A and 0x6C */ -static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { +/* Can be used by 0x67, 0x6A and 0x68 */ +static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { @@ -151,8 +151,7 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) case 0x67: case 0x68: case 0x6A: - case 0x6C: - return &ath_world_regdom_67_68_6A_6C; + return &ath_world_regdom_67_68_6A; default: WARN_ON(1); return ath_default_world_regdomain(); @@ -334,7 +333,6 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, case 0x63: case 0x66: case 0x67: - case 0x6C: ath_reg_apply_beaconing_flags(wiphy, initiator); break; case 0x68: diff --git a/trunk/drivers/net/wireless/ath/regd_common.h b/trunk/drivers/net/wireless/ath/regd_common.h index 24b53839fc3a..5c2cfe694152 100644 --- a/trunk/drivers/net/wireless/ath/regd_common.h +++ b/trunk/drivers/net/wireless/ath/regd_common.h @@ -86,7 +86,6 @@ enum EnumRd { WOR9_WORLD = 0x69, WORA_WORLD = 0x6A, WORB_WORLD = 0x6B, - WORC_WORLD = 0x6C, MKK3_MKKB = 0x80, MKK3_MKKA2 = 0x81, @@ -283,7 +282,6 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {WOR9_WORLD, NO_CTL, NO_CTL}, {WORA_WORLD, NO_CTL, NO_CTL}, {WORB_WORLD, NO_CTL, NO_CTL}, - {WORC_WORLD, NO_CTL, NO_CTL}, }; static struct country_code_to_enum_rd allCountries[] = { diff --git a/trunk/drivers/net/wireless/b43/phy_n.c b/trunk/drivers/net/wireless/b43/phy_n.c index 6755063f955a..8a00f9a95dbb 100644 --- a/trunk/drivers/net/wireless/b43/phy_n.c +++ b/trunk/drivers/net/wireless/b43/phy_n.c @@ -2281,7 +2281,6 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); - save_regs_phy[8] = 0; } else { save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); @@ -2290,8 +2289,6 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); - save_regs_phy[7] = 0; - save_regs_phy[8] = 0; } b43_nphy_rssi_select(dev, 5, type); @@ -3848,8 +3845,8 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, { struct b43_phy *phy = &dev->phy; - const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; - const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; + const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; + const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; u8 tmp; diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/trunk/drivers/net/wireless/iwlegacy/iwl-4965-rs.c index 89509392ef5d..31ac672b64e1 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl-4965-rs.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl-4965-rs.c @@ -2860,6 +2860,7 @@ static struct rate_control_ops rs_4965_ops = { int iwl4965_rate_control_register(void) { + pr_err("Registering 4965 rate control operations\n"); return ieee80211_rate_control_register(&rs_4965_ops); } diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c b/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c index f8870543d68f..d484c3678163 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -3173,7 +3173,7 @@ static void iwl4965_hw_detect(struct iwl_priv *priv) { priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV); priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG); - priv->rev_id = priv->pci_dev->revision; + pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); } diff --git a/trunk/drivers/net/wireless/iwlwifi/Makefile b/trunk/drivers/net/wireless/iwlwifi/Makefile index bb6a737de61f..9d6ee836426c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Makefile +++ b/trunk/drivers/net/wireless/iwlwifi/Makefile @@ -1,8 +1,8 @@ # AGN obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o -iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o +iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c index baf80111efaf..27c5007e577c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -45,6 +45,7 @@ #include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" +#include "iwl-agn-led.h" #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ @@ -56,10 +57,12 @@ #define IWL100_UCODE_API_MIN 5 #define IWL1000_FW_PRE "iwlwifi-1000-" -#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" +#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" +#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) #define IWL100_FW_PRE "iwlwifi-100-" -#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" +#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" +#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) /* @@ -138,6 +141,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; @@ -175,12 +179,21 @@ static struct iwl_lib_ops iwl1000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .load_ucode = iwlagn_load_ucode, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .apm_ops = { @@ -195,13 +208,20 @@ static struct iwl_lib_ops iwl1000_lib = { EEPROM_REG_BAND_4_CHANNELS, EEPROM_REG_BAND_5_CHANNELS, EEPROM_REG_BAND_24_HT40_CHANNELS, - EEPROM_REGULATORY_BAND_NO_HT40, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -214,12 +234,19 @@ static struct iwl_lib_ops iwl1000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static const struct iwl_ops iwl1000_ops = { .lib = &iwl1000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl1000_base_params = { @@ -227,6 +254,8 @@ static struct iwl_base_params iwl1000_base_params = { .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .eeprom_size = OTP_LOW_IMAGE_SIZE, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, + .set_l0s = true, + .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, .led_compensation = 51, @@ -236,6 +265,9 @@ static struct iwl_base_params iwl1000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 128, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; static struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c index e76e02c28928..d7b6126408c9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -46,6 +46,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" +#include "iwl-agn-led.h" #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ @@ -59,13 +60,16 @@ #define IWL200_UCODE_API_MIN 5 #define IWL2030_FW_PRE "iwlwifi-2030-" -#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" +#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" +#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api) #define IWL2000_FW_PRE "iwlwifi-2000-" -#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" +#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" +#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api) #define IWL200_FW_PRE "iwlwifi-200-" -#define IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" +#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" +#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api) static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { @@ -97,8 +101,6 @@ static void iwl2000_nic_config(struct iwl_priv *priv) iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); - if (priv->cfg->disable_otp_refresh) - iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010); } static struct iwl_sensitivity_ranges iwl2000_sensitivity = { @@ -145,6 +147,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; @@ -256,6 +259,8 @@ static struct iwl_lib_ops iwl2000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, @@ -263,6 +268,13 @@ static struct iwl_lib_ops iwl2000_lib = { .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .load_ucode = iwlagn_load_ucode, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl2030_hw_channel_switch, @@ -278,7 +290,7 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_REG_BAND_4_CHANNELS, EEPROM_REG_BAND_5_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS, - EEPROM_REGULATORY_BAND_NO_HT40, + EEPROM_REG_BAND_52_HT40_CHANNELS }, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, @@ -286,6 +298,13 @@ static struct iwl_lib_ops iwl2000_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -298,30 +317,43 @@ static struct iwl_lib_ops iwl2000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static const struct iwl_ops iwl2000_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl2030_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl200_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl230_ops = { .lib = &iwl2000_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl2000_base_params = { @@ -329,6 +361,8 @@ static struct iwl_base_params iwl2000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 51, @@ -339,6 +373,9 @@ static struct iwl_base_params iwl2000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; @@ -348,6 +385,8 @@ static struct iwl_base_params iwl2030_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 57, @@ -358,6 +397,9 @@ static struct iwl_base_params iwl2030_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; @@ -367,6 +409,7 @@ static struct iwl_ht_params iwl2000_ht_params = { }; static struct iwl_bt_params iwl2030_bt_params = { + .bt_statistics = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, .agg_time_limit = BT_AGG_THRESHOLD_DEF, @@ -388,8 +431,7 @@ static struct iwl_bt_params iwl2030_bt_params = { .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ - .iq_invert = true, \ - .disable_otp_refresh = true \ + .iq_invert = true \ struct iwl_cfg iwl2000_2bgn_cfg = { .name = "2000 Series 2x2 BGN", @@ -429,6 +471,37 @@ struct iwl_cfg iwl2030_2bg_cfg = { IWL_DEVICE_2030, }; +#define IWL_DEVICE_6035 \ + .fw_name_pre = IWL2030_FW_PRE, \ + .ucode_api_max = IWL2030_UCODE_API_MAX, \ + .ucode_api_min = IWL2030_UCODE_API_MIN, \ + .eeprom_ver = EEPROM_6035_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6035_TX_POWER_VERSION, \ + .ops = &iwl2030_ops, \ + .mod_params = &iwlagn_mod_params, \ + .base_params = &iwl2030_base_params, \ + .bt_params = &iwl2030_bt_params, \ + .need_dc_calib = true, \ + .need_temp_offset_calib = true, \ + .led_mode = IWL_LED_RF_STATE, \ + .adv_pm = true \ + +struct iwl_cfg iwl6035_2agn_cfg = { + .name = "2000 Series 2x2 AGN/BT", + IWL_DEVICE_6035, + .ht_params = &iwl2000_ht_params, +}; + +struct iwl_cfg iwl6035_2abg_cfg = { + .name = "2000 Series 2x2 ABG/BT", + IWL_DEVICE_6035, +}; + +struct iwl_cfg iwl6035_2bg_cfg = { + .name = "2000 Series 2x2 BG/BT", + IWL_DEVICE_6035, +}; + #define IWL_DEVICE_200 \ .fw_name_pre = IWL200_FW_PRE, \ .ucode_api_max = IWL200_UCODE_API_MAX, \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 05ad47628b63..3975e45e7500 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index 655afc19f68f..22e045b5bcee 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -45,6 +45,7 @@ #include "iwl-sta.h" #include "iwl-helpers.h" #include "iwl-agn.h" +#include "iwl-agn-led.h" #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" #include "iwl-agn-debugfs.h" @@ -58,10 +59,12 @@ #define IWL5150_UCODE_API_MIN 1 #define IWL5000_FW_PRE "iwlwifi-5000-" -#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" +#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" +#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api) #define IWL5150_FW_PRE "iwlwifi-5150-" -#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" +#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" +#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) /* NIC configuration for 5000 series */ static void iwl5000_nic_config(struct iwl_priv *priv) @@ -182,6 +185,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; @@ -227,6 +231,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; @@ -258,7 +263,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) u32 vt = 0; s32 offset = iwl_temp_calib_to_offset(priv); - vt = le32_to_cpu(priv->statistics.common.temperature); + vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature); vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; /* now vt hold the temperature in Kelvin */ priv->temperature = KELVIN_TO_CELSIUS(vt); @@ -343,12 +348,21 @@ static struct iwl_lib_ops iwl5000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .load_ucode = iwlagn_load_ucode, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, @@ -371,6 +385,13 @@ static struct iwl_lib_ops iwl5000_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -383,6 +404,11 @@ static struct iwl_lib_ops iwl5000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static struct iwl_lib_ops iwl5150_lib = { @@ -390,12 +416,20 @@ static struct iwl_lib_ops iwl5150_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .load_ucode = iwlagn_load_ucode, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl5000_hw_channel_switch, @@ -418,6 +452,13 @@ static struct iwl_lib_ops iwl5150_lib = { .calib_version = iwlagn_eeprom_calib_version, .query_addr = iwlagn_eeprom_query_addr, }, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwl5150_temperature, }, @@ -430,18 +471,27 @@ static struct iwl_lib_ops iwl5150_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static const struct iwl_ops iwl5000_ops = { .lib = &iwl5000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl5150_ops = { .lib = &iwl5150_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl5000_base_params = { @@ -449,12 +499,17 @@ static struct iwl_base_params iwl5000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, + .set_l0s = true, + .use_bsm = false, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h index b27986e57c92..47891e16a758 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c index 905eb57f7cab..a745b01c0ec1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -46,6 +46,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" +#include "iwl-agn-led.h" #include "iwl-agn-debugfs.h" /* Highest firmware API version supported */ @@ -59,16 +60,20 @@ #define IWL6000G2_UCODE_API_MIN 4 #define IWL6000_FW_PRE "iwlwifi-6000-" -#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" +#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" +#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) #define IWL6050_FW_PRE "iwlwifi-6050-" -#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" +#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" +#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) #define IWL6005_FW_PRE "iwlwifi-6000g2a-" -#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" +#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" +#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api) #define IWL6030_FW_PRE "iwlwifi-6000g2b-" -#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" +#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" +#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api) static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { @@ -171,6 +176,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + priv->hw_params.max_bsm_size = 0; priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; @@ -282,12 +288,21 @@ static struct iwl_lib_ops iwl6000_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .load_ucode = iwlagn_load_ucode, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, @@ -311,6 +326,13 @@ static struct iwl_lib_ops iwl6000_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -323,6 +345,11 @@ static struct iwl_lib_ops iwl6000_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static struct iwl_lib_ops iwl6030_lib = { @@ -330,6 +357,8 @@ static struct iwl_lib_ops iwl6030_lib = { .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, .txq_set_sched = iwlagn_txq_set_sched, + .txq_agg_enable = iwlagn_txq_agg_enable, + .txq_agg_disable = iwlagn_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, .txq_init = iwl_hw_tx_queue_init, @@ -337,6 +366,13 @@ static struct iwl_lib_ops iwl6030_lib = { .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, + .load_ucode = iwlagn_load_ucode, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .init_alive_start = iwlagn_init_alive_start, + .alive_notify = iwlagn_alive_notify, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .set_channel_switch = iwl6000_hw_channel_switch, @@ -360,6 +396,13 @@ static struct iwl_lib_ops iwl6030_lib = { .query_addr = iwlagn_eeprom_query_addr, .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, + .isr_ops = { + .isr = iwl_isr_ict, + .free = iwl_free_isr_ict, + .alloc = iwl_alloc_isr_ict, + .reset = iwl_reset_ict, + .disable = iwl_disable_ict, + }, .temp_ops = { .temperature = iwlagn_temperature, }, @@ -372,6 +415,11 @@ static struct iwl_lib_ops iwl6030_lib = { }, .txfifo_flush = iwlagn_txfifo_flush, .dev_txfifo_flush = iwlagn_dev_txfifo_flush, + .tt_ops = { + .lower_power_detection = iwl_tt_is_low_power_state, + .tt_power_mode = iwl_tt_current_power_mode, + .ct_kill_check = iwl_check_for_ct_kill, + } }; static struct iwl_nic_ops iwl6050_nic_ops = { @@ -386,26 +434,34 @@ static const struct iwl_ops iwl6000_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6050_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, .nic = &iwl6050_nic_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6150_ops = { .lib = &iwl6000_lib, .hcmd = &iwlagn_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, .nic = &iwl6150_nic_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static const struct iwl_ops iwl6030_ops = { .lib = &iwl6030_lib, .hcmd = &iwlagn_bt_hcmd, .utils = &iwlagn_hcmd_utils, + .led = &iwlagn_led_ops, + .ieee80211_ops = &iwlagn_hw_ops, }; static struct iwl_base_params iwl6000_base_params = { @@ -413,6 +469,8 @@ static struct iwl_base_params iwl6000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 51, @@ -423,6 +481,9 @@ static struct iwl_base_params iwl6000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; @@ -431,6 +492,8 @@ static struct iwl_base_params iwl6050_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, .shadow_ram_support = true, .led_compensation = 51, @@ -441,6 +504,9 @@ static struct iwl_base_params iwl6050_base_params = { .chain_noise_scale = 1500, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 1024, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; static struct iwl_base_params iwl6000_g2_base_params = { @@ -448,6 +514,8 @@ static struct iwl_base_params iwl6000_g2_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 57, @@ -458,6 +526,9 @@ static struct iwl_base_params iwl6000_g2_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, .shadow_reg_enable = true, }; @@ -467,6 +538,7 @@ static struct iwl_ht_params iwl6000_ht_params = { }; static struct iwl_bt_params iwl6000_bt_params = { + .bt_statistics = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, .agg_time_limit = BT_AGG_THRESHOLD_DEF, @@ -541,22 +613,6 @@ struct iwl_cfg iwl6030_2bg_cfg = { IWL_DEVICE_6030, }; -struct iwl_cfg iwl6035_2agn_cfg = { - .name = "6035 Series 2x2 AGN/BT", - IWL_DEVICE_6030, - .ht_params = &iwl6000_ht_params, -}; - -struct iwl_cfg iwl6035_2abg_cfg = { - .name = "6035 Series 2x2 ABG/BT", - IWL_DEVICE_6030, -}; - -struct iwl_cfg iwl6035_2bg_cfg = { - .name = "6035 Series 2x2 BG/BT", - IWL_DEVICE_6030, -}; - struct iwl_cfg iwl1030_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", IWL_DEVICE_6030, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 0f6bb9b2e642..9006293e740c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -605,7 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) IWL_DEBUG_CALIB(priv, "<lock, flags); - rx_info = &priv->statistics.rx_non_phy; - ofdm = &priv->statistics.rx_ofdm; - cck = &priv->statistics.rx_cck; + if (iwl_bt_statistics(priv)) { + rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> + rx.general.common); + ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); + cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck); + } else { + rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general); + ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm); + cck = &(((struct iwl_notif_statistics *)resp)->rx.cck); + } if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -844,7 +851,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. */ -void iwl_chain_noise_calibration(struct iwl_priv *priv) +void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) { struct iwl_chain_noise_data *data = NULL; @@ -889,9 +896,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) } spin_lock_irqsave(&priv->lock, flags); - - rx_info = &priv->statistics.rx_non_phy; - + if (iwl_bt_statistics(priv)) { + rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> + rx.general.common); + } else { + rx_info = &(((struct iwl_notif_statistics *)stat_resp)-> + rx.general); + } if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -900,9 +911,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); rxon_chnum = le16_to_cpu(ctx->staging.channel); - stat_band24 = - !!(priv->statistics.flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); - stat_chnum = le32_to_cpu(priv->statistics.flag) >> 16; + if (iwl_bt_statistics(priv)) { + stat_band24 = !!(((struct iwl_bt_notif_statistics *) + stat_resp)->flag & + STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *) + stat_resp)->flag) >> 16; + } else { + stat_band24 = !!(((struct iwl_notif_statistics *) + stat_resp)->flag & + STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *) + stat_resp)->flag) >> 16; + } /* Make sure we accumulate data for just the associated channel * (even if scanning). */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index 4ef4dd934254..e37ae7261630 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,8 +66,8 @@ #include "iwl-core.h" #include "iwl-commands.h" -void iwl_chain_noise_calibration(struct iwl_priv *priv); -void iwl_sensitivity_calibration(struct iwl_priv *priv); +void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp); +void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp); void iwl_init_sensitivity(struct iwl_priv *priv); void iwl_reset_run_time_calib(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 71a5f31cd7cc..b500aaae53ec 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -1,30 +1,30 @@ /****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ +* +* GPL LICENSE SUMMARY +* +* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, +* USA +* +* The full GNU General Public License is included in this distribution +* in the file called LICENSE.GPL. +* +* Contact Information: +* Intel Linux Wireless +* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +*****************************************************************************/ #include "iwl-agn.h" #include "iwl-agn-debugfs.h" @@ -39,7 +39,10 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) int p = 0; u32 flag; - flag = le32_to_cpu(priv->statistics.flag); + if (iwl_bt_statistics(priv)) + flag = le32_to_cpu(priv->_agn.statistics_bt.flag); + else + flag = le32_to_cpu(priv->_agn.statistics.flag); p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); if (flag & UCODE_STATISTICS_CLEAR_MSK) @@ -85,22 +88,43 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, * the last statistics notification from uCode * might not reflect the current uCode activity */ - ofdm = &priv->statistics.rx_ofdm; - cck = &priv->statistics.rx_cck; - general = &priv->statistics.rx_non_phy; - ht = &priv->statistics.rx_ofdm_ht; - accum_ofdm = &priv->accum_stats.rx_ofdm; - accum_cck = &priv->accum_stats.rx_cck; - accum_general = &priv->accum_stats.rx_non_phy; - accum_ht = &priv->accum_stats.rx_ofdm_ht; - delta_ofdm = &priv->delta_stats.rx_ofdm; - delta_cck = &priv->delta_stats.rx_cck; - delta_general = &priv->delta_stats.rx_non_phy; - delta_ht = &priv->delta_stats.rx_ofdm_ht; - max_ofdm = &priv->max_delta_stats.rx_ofdm; - max_cck = &priv->max_delta_stats.rx_cck; - max_general = &priv->max_delta_stats.rx_non_phy; - max_ht = &priv->max_delta_stats.rx_ofdm_ht; + if (iwl_bt_statistics(priv)) { + ofdm = &priv->_agn.statistics_bt.rx.ofdm; + cck = &priv->_agn.statistics_bt.rx.cck; + general = &priv->_agn.statistics_bt.rx.general.common; + ht = &priv->_agn.statistics_bt.rx.ofdm_ht; + accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm; + accum_cck = &priv->_agn.accum_statistics_bt.rx.cck; + accum_general = + &priv->_agn.accum_statistics_bt.rx.general.common; + accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht; + delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm; + delta_cck = &priv->_agn.delta_statistics_bt.rx.cck; + delta_general = + &priv->_agn.delta_statistics_bt.rx.general.common; + delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht; + max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm; + max_cck = &priv->_agn.max_delta_bt.rx.cck; + max_general = &priv->_agn.max_delta_bt.rx.general.common; + max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht; + } else { + ofdm = &priv->_agn.statistics.rx.ofdm; + cck = &priv->_agn.statistics.rx.cck; + general = &priv->_agn.statistics.rx.general; + ht = &priv->_agn.statistics.rx.ofdm_ht; + accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; + accum_cck = &priv->_agn.accum_statistics.rx.cck; + accum_general = &priv->_agn.accum_statistics.rx.general; + accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; + delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; + delta_cck = &priv->_agn.delta_statistics.rx.cck; + delta_general = &priv->_agn.delta_statistics.rx.general; + delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; + max_ofdm = &priv->_agn.max_delta.rx.ofdm; + max_cck = &priv->_agn.max_delta.rx.cck; + max_general = &priv->_agn.max_delta.rx.general; + max_ht = &priv->_agn.max_delta.rx.ofdm_ht; + } pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, @@ -507,13 +531,20 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, } /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - tx = &priv->statistics.tx; - accum_tx = &priv->accum_stats.tx; - delta_tx = &priv->delta_stats.tx; - max_tx = &priv->max_delta_stats.tx; + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + if (iwl_bt_statistics(priv)) { + tx = &priv->_agn.statistics_bt.tx; + accum_tx = &priv->_agn.accum_statistics_bt.tx; + delta_tx = &priv->_agn.delta_statistics_bt.tx; + max_tx = &priv->_agn.max_delta_bt.tx; + } else { + tx = &priv->_agn.statistics.tx; + accum_tx = &priv->_agn.accum_statistics.tx; + delta_tx = &priv->_agn.delta_statistics.tx; + max_tx = &priv->_agn.max_delta.tx; + } pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, @@ -700,21 +731,36 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, } /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - general = &priv->statistics.common; - dbg = &priv->statistics.common.dbg; - div = &priv->statistics.common.div; - accum_general = &priv->accum_stats.common; - accum_dbg = &priv->accum_stats.common.dbg; - accum_div = &priv->accum_stats.common.div; - delta_general = &priv->delta_stats.common; - max_general = &priv->max_delta_stats.common; - delta_dbg = &priv->delta_stats.common.dbg; - max_dbg = &priv->max_delta_stats.common.dbg; - delta_div = &priv->delta_stats.common.div; - max_div = &priv->max_delta_stats.common.div; + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + if (iwl_bt_statistics(priv)) { + general = &priv->_agn.statistics_bt.general.common; + dbg = &priv->_agn.statistics_bt.general.common.dbg; + div = &priv->_agn.statistics_bt.general.common.div; + accum_general = &priv->_agn.accum_statistics_bt.general.common; + accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg; + accum_div = &priv->_agn.accum_statistics_bt.general.common.div; + delta_general = &priv->_agn.delta_statistics_bt.general.common; + max_general = &priv->_agn.max_delta_bt.general.common; + delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg; + max_dbg = &priv->_agn.max_delta_bt.general.common.dbg; + delta_div = &priv->_agn.delta_statistics_bt.general.common.div; + max_div = &priv->_agn.max_delta_bt.general.common.div; + } else { + general = &priv->_agn.statistics.general.common; + dbg = &priv->_agn.statistics.general.common.dbg; + div = &priv->_agn.statistics.general.common.div; + accum_general = &priv->_agn.accum_statistics.general.common; + accum_dbg = &priv->_agn.accum_statistics.general.common.dbg; + accum_div = &priv->_agn.accum_statistics.general.common.div; + delta_general = &priv->_agn.delta_statistics.general.common; + max_general = &priv->_agn.max_delta.general.common; + delta_dbg = &priv->_agn.delta_statistics.general.common.dbg; + max_dbg = &priv->_agn.max_delta.general.common.dbg; + delta_div = &priv->_agn.delta_statistics.general.common.div; + max_div = &priv->_agn.max_delta.general.common.div; + } pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, @@ -830,8 +876,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ - bt = &priv->statistics.bt_activity; - accum_bt = &priv->accum_stats.bt_activity; + bt = &priv->_agn.statistics_bt.general.activity; + accum_bt = &priv->_agn.accum_statistics_bt.general.activity; pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); @@ -872,8 +918,10 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", - le32_to_cpu(priv->statistics.num_bt_kills), - priv->statistics.accum_num_bt_kills); + le32_to_cpu(priv->_agn.statistics_bt.rx. + general.num_bt_kills), + priv->_agn.accum_statistics_bt.rx. + general.num_bt_kills); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h index 9a3f329e508f..f2573b5486cd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 3bcaa10f9929..27b5a3eec9dc 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -103,7 +103,7 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); if (ret >= 0) { - IWL_DEBUG_EEPROM(priv, + IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n", count+1); return ret; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 861cc93957a9..41543ad4cb84 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 7bd19f4e66de..a52b82c8e7a6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index 34d77d22a360..b5cb3be0eb4b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -59,6 +59,8 @@ void iwl_free_isr_ict(struct iwl_priv *priv) int iwl_alloc_isr_ict(struct iwl_priv *priv) { + if (priv->cfg->base_params->use_isr_legacy) + return 0; /* allocate shrared data table */ priv->_agn.ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c new file mode 100644 index 000000000000..c1190d965614 --- /dev/null +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.c @@ -0,0 +1,73 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwl-commands.h" +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-agn-led.h" + +/* Send led command */ +static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_LEDS_CMD, + .len = sizeof(struct iwl_led_cmd), + .data = led_cmd, + .flags = CMD_ASYNC, + .callback = NULL, + }; + u32 reg; + + reg = iwl_read32(priv, CSR_LED_REG); + if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) + iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + + return iwl_send_cmd(priv, &cmd); +} + +/* Set led register off */ +void iwlagn_led_enable(struct iwl_priv *priv) +{ + iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); +} + +const struct iwl_led_ops iwlagn_led_ops = { + .cmd = iwl_send_led_cmd, +}; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h new file mode 100644 index 000000000000..96f323dc5dd6 --- /dev/null +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-led.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#ifndef __iwl_agn_led_h__ +#define __iwl_agn_led_h__ + +extern const struct iwl_led_ops iwlagn_led_ops; +void iwlagn_led_enable(struct iwl_priv *priv); + +#endif /* __iwl_agn_led_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e202a40cbcb7..08ccb9496f76 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -172,7 +172,6 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) static void iwlagn_set_tx_status(struct iwl_priv *priv, struct ieee80211_tx_info *info, - struct iwl_rxon_context *ctx, struct iwlagn_tx_resp *tx_resp, int txq_id, bool is_agg) { @@ -187,13 +186,6 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv, if (!iwl_is_tx_success(status)) iwlagn_count_tx_err_status(priv, status); - if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && - iwl_is_associated_ctx(ctx) && ctx->vif && - ctx->vif->type == NL80211_IFTYPE_STATION) { - ctx->last_tx_rejected = true; - iwl_stop_queue(priv, &priv->txq[txq_id]); - } - IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " "0x%x retries %d\n", txq_id, @@ -250,16 +242,15 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, /* # frames attempted by Tx command */ if (agg->frame_count == 1) { - struct iwl_tx_info *txb; - /* Only one frame was attempted; no block-ack will arrive */ idx = start_idx; IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); - txb = &priv->txq[txq_id].txb[idx]; - iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb), - txb->ctx, tx_resp, txq_id, true); + iwlagn_set_tx_status(priv, + IEEE80211_SKB_CB( + priv->txq[txq_id].txb[idx].skb), + tx_resp, txq_id, true); agg->wait_for_ba = 0; } else { /* Two or more frames were attempted; expect block-ack */ @@ -400,8 +391,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct ieee80211_tx_info *info; struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - struct iwl_tx_info *txb; - u32 status = le16_to_cpu(tx_resp->status.status); + u32 status = le16_to_cpu(tx_resp->status.status); int tid; int sta_id; int freed; @@ -416,8 +406,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, } txq->time_stamp = jiffies; - txb = &txq->txb[txq->q.read_ptr]; - info = IEEE80211_SKB_CB(txb->skb); + info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); memset(&info->status, 0, sizeof(info->status)); tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> @@ -461,14 +450,12 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, iwl_wake_queue(priv, txq); } } else { - iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp, - txq_id, false); + iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false); freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && - iwl_queue_space(&txq->q) > txq->q.low_mark && - status != TX_STATUS_FAIL_PASSIVE_NO_RX) + (iwl_queue_space(&txq->q) > txq->q.low_mark)) iwl_wake_queue(priv, txq); } @@ -483,6 +470,8 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) /* init calibration handlers */ priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = iwlagn_rx_calib_result; + priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = + iwlagn_rx_calib_complete; priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; /* set up notification wait support */ @@ -493,10 +482,8 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) void iwlagn_setup_deferred_work(struct iwl_priv *priv) { - /* - * nothing need to be done here anymore - * still keep for future use if needed - */ + /* in agn, the tx power calibration is done in uCode */ + priv->disable_tx_power_cal = 1; } int iwlagn_hw_valid_rtc_data_addr(u32 addr) @@ -547,7 +534,9 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) void iwlagn_temperature(struct iwl_priv *priv) { /* store temperature from correct statistics (in Celsius) */ - priv->temperature = le32_to_cpu(priv->statistics.common.temperature); + priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ? + priv->_agn.statistics_bt.general.common.temperature : + priv->_agn.statistics.general.common.temperature); iwl_tt_handler(priv); } @@ -663,7 +652,8 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - rb_timeout = RX_RB_TIMEOUT; + if (!priv->cfg->base_params->use_isr_legacy) + rb_timeout = RX_RB_TIMEOUT; if (priv->cfg->mod_params->amsdu_size_8K) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; @@ -923,6 +913,7 @@ void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; + priv->alloc_rxb_page++; spin_unlock_irqrestore(&rxq->lock, flags); } @@ -2254,44 +2245,34 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) /* notification wait support */ void iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, - u8 cmd, void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data) + struct iwl_rx_packet *pkt), + u8 cmd) { wait_entry->fn = fn; - wait_entry->fn_data = fn_data; wait_entry->cmd = cmd; wait_entry->triggered = false; - wait_entry->aborted = false; spin_lock_bh(&priv->_agn.notif_wait_lock); list_add(&wait_entry->list, &priv->_agn.notif_waits); spin_unlock_bh(&priv->_agn.notif_wait_lock); } -int iwlagn_wait_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - unsigned long timeout) +signed long iwlagn_wait_notification(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry, + unsigned long timeout) { int ret; ret = wait_event_timeout(priv->_agn.notif_waitq, - wait_entry->triggered || wait_entry->aborted, + wait_entry->triggered, timeout); spin_lock_bh(&priv->_agn.notif_wait_lock); list_del(&wait_entry->list); spin_unlock_bh(&priv->_agn.notif_wait_lock); - if (wait_entry->aborted) - return -EIO; - - /* return value is always >= 0 */ - if (ret <= 0) - return -ETIMEDOUT; - return 0; + return ret; } void iwlagn_remove_notification(struct iwl_priv *priv, @@ -2301,78 +2282,3 @@ void iwlagn_remove_notification(struct iwl_priv *priv, list_del(&wait_entry->list); spin_unlock_bh(&priv->_agn.notif_wait_lock); } - -int iwlagn_start_device(struct iwl_priv *priv) -{ - int ret; - - if (iwl_prepare_card_hw(priv)) { - IWL_WARN(priv, "Exit HW not ready\n"); - return -EIO; - } - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - if (iwl_is_rfkill(priv)) { - wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - iwl_enable_interrupts(priv); - return -ERFKILL; - } - - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - - ret = iwlagn_hw_nic_init(priv); - if (ret) { - IWL_ERR(priv, "Unable to init nic\n"); - return ret; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - return 0; -} - -void iwlagn_stop_device(struct iwl_priv *priv) -{ - unsigned long flags; - - /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - - /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); - - /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); - - iwlagn_txq_ctx_stop(priv); - iwlagn_rxq_stop(priv); - - /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); - udelay(5); - - /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv); -} diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index dbe6295bbf23..d03b4734c892 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -115,18 +115,13 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { /* FIXME:RS: ^^ should be INV (legacy) */ }; -static inline u8 rs_extract_rate(u32 rate_n_flags) -{ - return (u8)(rate_n_flags & RATE_MCS_RATE_MSK); -} - static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) { int idx = 0; /* HT rate format */ if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = rs_extract_rate(rate_n_flags); + idx = (rate_n_flags & 0xff); if (idx >= IWL_RATE_MIMO3_6M_PLCP) idx = idx - IWL_RATE_MIMO3_6M_PLCP; @@ -143,8 +138,7 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) /* legacy rate format, search for match in table */ } else { for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) - if (iwl_rates[idx].plcp == - rs_extract_rate(rate_n_flags)) + if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) return idx; } @@ -245,6 +239,11 @@ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { #define MCS_INDEX_PER_STREAM (8) +static inline u8 rs_extract_rate(u32 rate_n_flags) +{ + return (u8)(rate_n_flags & 0xFF); +} + static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) { window->data = 0; @@ -2771,13 +2770,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, gfp_t gfp) { + struct iwl_lq_sta *lq_sta; struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; struct iwl_priv *priv; priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE(priv, "create station rate scale window\n"); - return &sta_priv->lq_sta; + lq_sta = &sta_priv->lq_sta; + + return lq_sta; } /* @@ -2910,8 +2912,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, ant_toggle_cnt = 1; repeat_rate = IWL_NUMBER_TRY; } else { - repeat_rate = min(IWL_HT_NUMBER_TRY, - LINK_QUAL_AGG_DISABLE_START_DEF - 1); + repeat_rate = IWL_HT_NUMBER_TRY; } lq_cmd->general_params.mimo_delimiter = @@ -3256,6 +3257,7 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, { char buff[120]; int desc = 0; + ssize_t ret; struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; @@ -3272,7 +3274,8 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, "Bit Rate= %d Mb/s\n", iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - return simple_read_from_buffer(user_buf, count, ppos, buff, desc); + ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); + return ret; } static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index bdae82e7fa90..184828c72b31 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -41,6 +41,20 @@ struct iwl_rate_info { u8 next_rs_tgg; /* next rate used in TGG rs algo */ }; +struct iwl3945_rate_info { + u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ + u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ + u8 prev_ieee; /* previous rate in IEEE speeds */ + u8 next_ieee; /* next rate in IEEE speeds */ + u8 prev_rs; /* previous rate used in rs algo */ + u8 next_rs; /* next rate used in rs algo */ + u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ + u8 next_rs_tgg; /* next rate used in TGG rs algo */ + u8 table_rs_index; /* index in rate scale table cmd */ + u8 prev_table_rs; /* prev in rate table cmd */ +}; + + /* * These serve as indexes into * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; @@ -61,6 +75,7 @@ enum { IWL_RATE_60M_INDEX, IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/ IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1, /* Excluding 60M */ + IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1, IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, IWL_RATE_INVALID = IWL_RATE_COUNT, }; @@ -83,6 +98,7 @@ enum { enum { IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, + IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX, IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, @@ -197,6 +213,7 @@ enum { IWL_CCK_BASIC_RATES_MASK) #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) +#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1) #define IWL_INVALID_VALUE -1 @@ -436,9 +453,19 @@ static inline u8 first_antenna(u8 mask) } +/** + * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info + * + * The specific throughput table used is based on the type of network + * the associated with, including A, B, G, and G w/ TGG protection + */ +extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); + /* Initialize station's rate scaling information after adding station */ extern void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id); +extern void iwl3945_rs_rate_init(struct iwl_priv *priv, + struct ieee80211_sta *sta, u8 sta_id); /** * iwl_rate_control_register - Register the rate control algorithm callbacks @@ -451,6 +478,7 @@ extern void iwl_rs_rate_init(struct iwl_priv *priv, * */ extern int iwlagn_rate_control_register(void); +extern int iwl3945_rate_control_register(void); /** * iwl_rate_control_unregister - Unregister the rate control callbacks @@ -459,5 +487,6 @@ extern int iwlagn_rate_control_register(void); * the driver is unloaded. */ extern void iwlagn_rate_control_unregister(void); +extern void iwl3945_rate_control_unregister(void); #endif /* __iwl_agn__rs__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 202ef64a14d5..fbbde0712fa5 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -29,7 +29,6 @@ #include "iwl-sta.h" #include "iwl-core.h" #include "iwl-agn-calib.h" -#include "iwl-helpers.h" static int iwlagn_disable_bss(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -58,9 +57,8 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, u8 old_dev_type = send->dev_type; int ret; - iwlagn_init_notification_wait(priv, &disable_wait, - REPLY_WIPAN_DEACTIVATION_COMPLETE, - NULL, NULL); + iwlagn_init_notification_wait(priv, &disable_wait, NULL, + REPLY_WIPAN_DEACTIVATION_COMPLETE); send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; @@ -73,9 +71,13 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); iwlagn_remove_notification(priv, &disable_wait); } else { - ret = iwlagn_wait_notification(priv, &disable_wait, HZ); - if (ret) + signed long wait_res; + + wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ); + if (wait_res == 0) { IWL_ERR(priv, "Timed out waiting for PAN disable\n"); + ret = -EIO; + } } return ret; @@ -593,18 +595,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, priv->timestamp = bss_conf->timestamp; ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; } else { - /* - * If we disassociate while there are pending - * frames, just wake up the queues and let the - * frames "escape" ... This shouldn't really - * be happening to start with, but we should - * not get stuck in this case either since it - * can happen if userspace gets confused. - */ - if (ctx->last_tx_rejected) { - ctx->last_tx_rejected = false; - iwl_wake_any_queue(priv, ctx); - } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 079275f2c64d..35f085ac336b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -474,7 +474,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); memset(&priv->stations[sta_id].sta.key, 0, - sizeof(struct iwl_keyinfo)); + sizeof(struct iwl4965_keyinfo)); priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 348f74f1c8e8..e3a8216a033c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h index d118ed29bf3f..d55060427cac 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 494de0e59cb4..2dd7d54a796f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -222,8 +222,13 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid) +int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, + int tx_fifo, int sta_id, int tid, u16 ssn_idx) { + unsigned long flags; + u16 ra_tid; + int ret; + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { @@ -235,34 +240,13 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, return -EINVAL; } - /* Modify device's station table to Tx this TID */ - return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); -} - -void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, - struct ieee80211_sta *sta, - int tid, int frame_limit) -{ - int sta_id, tx_fifo, txq_id, ssn_idx; - u16 ra_tid; - unsigned long flags; - struct iwl_tid_data *tid_data; - - sta_id = iwl_sta_id(sta); - if (WARN_ON(sta_id == IWL_INVALID_STATION)) - return; - if (WARN_ON(tid >= MAX_TID_COUNT)) - return; - - spin_lock_irqsave(&priv->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; - ssn_idx = SEQ_TO_SN(tid_data->seq_number); - txq_id = tid_data->agg.txq_id; - tx_fifo = tid_data->agg.tx_fifo; - spin_unlock_irqrestore(&priv->sta_lock, flags); - ra_tid = BUILD_RAxTID(sta_id, tid); + /* Modify device's station table to Tx this TID */ + ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); + if (ret) + return ret; + spin_lock_irqsave(&priv->lock, flags); /* Stop this Tx queue before configuring it */ @@ -287,10 +271,10 @@ void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, iwl_write_targ_mem(priv, priv->scd_base_addr + IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), - ((frame_limit << + ((SCD_WIN_SIZE << IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((frame_limit << + ((SCD_FRAME_LIMIT << IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); @@ -300,10 +284,12 @@ void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); spin_unlock_irqrestore(&priv->lock, flags); + + return 0; } -static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) +int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) { if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + @@ -1048,11 +1034,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data = &priv->stations[sta_id].tid[tid]; *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; - tid_data->agg.tx_fifo = tx_fifo; iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&priv->sta_lock, flags); - ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); + ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, + sta_id, tid, *ssn); if (ret) return ret; @@ -1139,7 +1125,8 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, * to deactivate the uCode queue, just return "success" to allow * mac80211 to clean up it own data. */ - iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); + priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, + tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -1168,7 +1155,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = get_fifo_from_tid(ctx, tid); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo); + priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, + ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); } @@ -1267,11 +1255,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, struct iwl_compressed_ba_resp *ba_resp) { - int sh; + int i, sh, ack; u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + int successes = 0; struct ieee80211_tx_info *info; - u64 bitmap, sent_bitmap; if (unlikely(!agg->wait_for_ba)) { if (unlikely(ba_resp->bitmap)) @@ -1285,42 +1273,70 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, /* Calculate shift to align block-ack bits with our Tx window bits */ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); - if (sh < 0) + if (sh < 0) /* tbw something is wrong with indices */ sh += 0x100; - /* - * Check for success or failure according to the - * transmitted bitmap and block-ack bitmap - */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - sent_bitmap = bitmap & agg->bitmap; - - /* Sanity check values reported by uCode */ - if (ba_resp->txed_2_done > ba_resp->txed) { - IWL_DEBUG_TX_REPLY(priv, - "bogus sent(%d) and ack(%d) count\n", - ba_resp->txed, ba_resp->txed_2_done); + if (agg->frame_count > (64 - sh)) { + IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); + return -1; + } + if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { /* - * set txed_2_done = txed, - * so it won't impact rate scale + * sent and ack information provided by uCode + * use it instead of figure out ourself */ - ba_resp->txed = ba_resp->txed_2_done; - } - IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", - ba_resp->txed, ba_resp->txed_2_done); + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); + /* + * set txed_2_done = txed, + * so it won't impact rate scale + */ + ba_resp->txed = ba_resp->txed_2_done; + } + IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", + ba_resp->txed, ba_resp->txed_2_done); + } else { + u64 bitmap, sent_bitmap; + + /* don't use 64-bit values for now */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + + /* check for success or failure according to the + * transmitted bitmap and block-ack bitmap */ + sent_bitmap = bitmap & agg->bitmap; + + /* For each frame attempted in aggregation, + * update driver's record of tx frame's status. */ + i = 0; + while (sent_bitmap) { + ack = sent_bitmap & 1ULL; + successes += ack; + IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", + ack ? "ACK" : "NACK", i, + (agg->start_idx + i) & 0xff, + agg->start_idx + i); + sent_bitmap >>= 1; + ++i; + } - /* Find the first ACKed frame to store the TX status */ - while (sent_bitmap && !(sent_bitmap & 1)) { - agg->start_idx = (agg->start_idx + 1) & 0xff; - sent_bitmap >>= 1; + IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", + (unsigned long long)bitmap); } info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_len = ba_resp->txed_2_done; - info->status.ampdu_len = ba_resp->txed; + if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { + info->status.ampdu_ack_len = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; + + } else { + info->status.ampdu_ack_len = successes; + info->status.ampdu_len = agg->frame_count; + } iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); return 0; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index c3ae2e44fcc9..d807e5e2b718 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -161,19 +161,47 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, } static int iwlagn_load_given_ucode(struct iwl_priv *priv, - struct fw_img *image) + struct fw_desc *inst_image, + struct fw_desc *data_image) { int ret = 0; - ret = iwlagn_load_section(priv, "INST", &image->code, + ret = iwlagn_load_section(priv, "INST", inst_image, IWLAGN_RTC_INST_LOWER_BOUND); if (ret) return ret; - return iwlagn_load_section(priv, "DATA", &image->data, + return iwlagn_load_section(priv, "DATA", data_image, IWLAGN_RTC_DATA_LOWER_BOUND); } +int iwlagn_load_ucode(struct iwl_priv *priv) +{ + int ret = 0; + + /* check whether init ucode should be loaded, or rather runtime ucode */ + if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { + IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); + ret = iwlagn_load_given_ucode(priv, + &priv->ucode_init, &priv->ucode_init_data); + if (!ret) { + IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); + priv->ucode_type = UCODE_INIT; + } + } else { + IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " + "Loading runtime ucode...\n"); + ret = iwlagn_load_given_ucode(priv, + &priv->ucode_code, &priv->ucode_data); + if (!ret) { + IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); + priv->ucode_type = UCODE_RT; + } + } + + return ret; +} + /* * Calibration */ @@ -269,9 +297,33 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv, iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); } -static int iwlagn_init_alive_start(struct iwl_priv *priv) +void iwlagn_rx_calib_complete(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { - int ret; + IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); + queue_work(priv->workqueue, &priv->restart); +} + +void iwlagn_init_alive_start(struct iwl_priv *priv) +{ + int ret = 0; + + /* initialize uCode was loaded... verify inst image. + * This is a paranoid check, because we would not have gotten the + * "initialize" alive if code weren't properly loaded. */ + if (iwl_verify_ucode(priv)) { + /* Runtime instruction load was bad; + * take it all the way back down so we can try again */ + IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); + goto restart; + } + + ret = priv->cfg->ops->lib->alive_notify(priv); + if (ret) { + IWL_WARN(priv, + "Could not complete ALIVE transition: %d\n", ret); + goto restart; + } if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) { @@ -281,25 +333,24 @@ static int iwlagn_init_alive_start(struct iwl_priv *priv) * no need to close the envlope since we are going * to load the runtime uCode later. */ - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); - if (ret) - return ret; } - - ret = iwlagn_send_calib_cfg(priv); - if (ret) - return ret; + iwlagn_send_calib_cfg(priv); /** * temperature offset calibration is only needed for runtime ucode, * so prepare the value now. */ if (priv->cfg->need_temp_offset_calib) - return iwlagn_set_temperature_offset_calib(priv); + iwlagn_set_temperature_offset_calib(priv); - return 0; + return; + +restart: + /* real restart (first load init_ucode) */ + queue_work(priv->workqueue, &priv->restart); } static int iwlagn_send_wimax_coex(struct iwl_priv *priv) @@ -362,30 +413,25 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) IWL_ERR(priv, "failed to send BT prio tbl command\n"); } -int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) +void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) { struct iwl_bt_coex_prot_env_cmd env_cmd; - int ret; env_cmd.action = action; env_cmd.type = type; - ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, - sizeof(env_cmd), &env_cmd); - if (ret) + if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, + sizeof(env_cmd), &env_cmd)) IWL_ERR(priv, "failed to send BT env command\n"); - return ret; } -static int iwlagn_alive_notify(struct iwl_priv *priv) +int iwlagn_alive_notify(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; - struct iwl_rxon_context *ctx; u32 a; unsigned long flags; int i, chan; u32 reg_val; - int ret; spin_lock_irqsave(&priv->lock, flags); @@ -454,8 +500,6 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); for (i = 0; i < 4; i++) atomic_set(&priv->queue_stop_count[i], 0); - for_each_context(priv, ctx) - ctx->last_tx_rejected = false; /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; @@ -483,15 +527,12 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - ret = iwlagn_send_wimax_coex(priv); - if (ret) - return ret; + iwlagn_send_wimax_coex(priv); - ret = iwlagn_set_Xtal_calib(priv); - if (ret) - return ret; + iwlagn_set_Xtal_calib(priv); + iwl_send_calib_results(priv); - return iwl_send_calib_results(priv); + return 0; } @@ -500,12 +541,11 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, - struct fw_desc *fw_desc) +static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) { - __le32 *image = (__le32 *)fw_desc->v_addr; - u32 len = fw_desc->len; u32 val; + int ret = 0; + u32 errcnt = 0; u32 i; IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); @@ -516,204 +556,104 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, * if IWL_DL_IO is set */ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) - return -EIO; + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) { + ret = -EIO; + errcnt++; + if (errcnt >= 3) + break; + } } - return 0; + return ret; } -static void iwl_print_mismatch_inst(struct iwl_priv *priv, - struct fw_desc *fw_desc) +/** + * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, + * looking at all data. + */ +static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, + u32 len) { - __le32 *image = (__le32 *)fw_desc->v_addr; - u32 len = fw_desc->len; u32 val; - u32 offs; - int errors = 0; + u32 save_len = len; + int ret = 0; + u32 errcnt; IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWLAGN_RTC_INST_LOWER_BOUND); - for (offs = 0; - offs < len && errors < 20; - offs += sizeof(u32), image++) { + errcnt = 0; + for (; len > 0; len -= sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ - val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + /* NOTE: Use the debugless read so we don't flood kernel log + * if IWL_DL_IO is set */ + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "uCode INST section at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - offs, val, le32_to_cpu(*image)); - errors++; + IWL_ERR(priv, "uCode INST section is invalid at " + "offset 0x%x, is 0x%x, s/b 0x%x\n", + save_len - len, val, le32_to_cpu(*image)); + ret = -EIO; + errcnt++; + if (errcnt >= 20) + break; } } + + if (!errcnt) + IWL_DEBUG_INFO(priv, + "ucode image in INSTRUCTION memory is good\n"); + + return ret; } /** * iwl_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) -{ - if (!iwlcore_verify_inst_sparse(priv, &img->code)) { - IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); - return 0; - } - - IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); - - iwl_print_mismatch_inst(priv, &img->code); - return -EIO; -} - -struct iwlagn_alive_data { - bool valid; - u8 subtype; -}; - -static void iwlagn_alive_fn(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data) +int iwl_verify_ucode(struct iwl_priv *priv) { - struct iwlagn_alive_data *alive_data = data; - struct iwl_alive_resp *palive; - - palive = &pkt->u.alive_frame; - - IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " - "0x%01X 0x%01X\n", - palive->is_valid, palive->ver_type, - palive->ver_subtype); - - priv->device_pointers.error_event_table = - le32_to_cpu(palive->error_event_table_ptr); - priv->device_pointers.log_event_table = - le32_to_cpu(palive->log_event_table_ptr); - - alive_data->subtype = palive->ver_subtype; - alive_data->valid = palive->is_valid == UCODE_VALID_OK; -} - -#define UCODE_ALIVE_TIMEOUT HZ -#define UCODE_CALIB_TIMEOUT (2*HZ) - -int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, - struct fw_img *image, - int subtype, int alternate_subtype) -{ - struct iwl_notification_wait alive_wait; - struct iwlagn_alive_data alive_data; + __le32 *image; + u32 len; int ret; - enum iwlagn_ucode_subtype old_type; - - ret = iwlagn_start_device(priv); - if (ret) - return ret; - - iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, - iwlagn_alive_fn, &alive_data); - - old_type = priv->ucode_type; - priv->ucode_type = subtype; - - ret = iwlagn_load_given_ucode(priv, image); - if (ret) { - priv->ucode_type = old_type; - iwlagn_remove_notification(priv, &alive_wait); - return ret; - } - - /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); - - /* - * Some things may run in the background now, but we - * just wait for the ALIVE notification here. - */ - ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); - if (ret) { - priv->ucode_type = old_type; - return ret; - } - - if (!alive_data.valid) { - IWL_ERR(priv, "Loaded ucode is not valid!\n"); - priv->ucode_type = old_type; - return -EIO; - } - - if (alive_data.subtype != subtype && - alive_data.subtype != alternate_subtype) { - IWL_ERR(priv, - "Loaded ucode is not expected type (got %d, expected %d)!\n", - alive_data.subtype, subtype); - priv->ucode_type = old_type; - return -EIO; - } - ret = iwl_verify_ucode(priv, image); - if (ret) { - priv->ucode_type = old_type; - return ret; - } - - /* delay a bit to give rfkill time to run */ - msleep(5); - - ret = iwlagn_alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition: %d\n", ret); - priv->ucode_type = old_type; - return ret; + /* Try bootstrap */ + image = (__le32 *)priv->ucode_boot.v_addr; + len = priv->ucode_boot.len; + ret = iwlcore_verify_inst_sparse(priv, image, len); + if (!ret) { + IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); + return 0; } - return 0; -} - -int iwlagn_run_init_ucode(struct iwl_priv *priv) -{ - struct iwl_notification_wait calib_wait; - int ret; - - lockdep_assert_held(&priv->mutex); - - /* No init ucode required? Curious, but maybe ok */ - if (!priv->ucode_init.code.len) + /* Try initialize */ + image = (__le32 *)priv->ucode_init.v_addr; + len = priv->ucode_init.len; + ret = iwlcore_verify_inst_sparse(priv, image, len); + if (!ret) { + IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); return 0; + } - if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) + /* Try runtime/protocol */ + image = (__le32 *)priv->ucode_code.v_addr; + len = priv->ucode_code.len; + ret = iwlcore_verify_inst_sparse(priv, image, len); + if (!ret) { + IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); return 0; + } - iwlagn_init_notification_wait(priv, &calib_wait, - CALIBRATION_COMPLETE_NOTIFICATION, - NULL, NULL); - - /* Will also start the device */ - ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, - UCODE_SUBTYPE_INIT, -1); - if (ret) - goto error; - - ret = iwlagn_init_alive_start(priv); - if (ret) - goto error; - - /* - * Some things may run in the background now, but we - * just wait for the calibration complete notification. - */ - ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); + IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - goto out; + /* Since nothing seems to match, show first several data entries in + * instruction SRAM, so maybe visual inspection will give a clue. + * Selection of bootstrap image (vs. other images) is arbitrary. */ + image = (__le32 *)priv->ucode_boot.v_addr; + len = priv->ucode_boot.len; + ret = iwl_verify_inst_full(priv, image, len); - error: - iwlagn_remove_notification(priv, &calib_wait); - out: - /* Whatever happened, stop the device */ - iwlagn_stop_device(priv); return ret; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index a4f1009cb137..321b18b59135 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -59,6 +59,7 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" +#include "iwl-agn-led.h" /****************************************************************************** @@ -253,10 +254,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) struct iwl_frame *frame; unsigned int frame_size; int rc; - struct iwl_host_cmd cmd = { - .id = REPLY_TX_BEACON, - .flags = CMD_SIZE_HUGE, - }; frame = iwl_get_free_frame(priv); if (!frame) { @@ -272,10 +269,8 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) return -EINVAL; } - cmd.len = frame_size; - cmd.data = &frame->u.cmd[0]; - - rc = iwl_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, + &frame->u.cmd[0]); iwl_free_frame(priv, frame); @@ -400,9 +395,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, return -EINVAL; } - if (WARN_ON(addr & ~DMA_BIT_MASK(36))) - return -EINVAL; - + BUG_ON(addr & ~DMA_BIT_MASK(36)); if (unlikely(addr & ~IWL_TX_DMA_MASK)) IWL_ERR(priv, "Unaligned address = %llx\n", (unsigned long long)addr); @@ -416,7 +409,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * - * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA + * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA * channels supported in hardware. */ int iwl_hw_tx_queue_init(struct iwl_priv *priv, @@ -490,14 +483,12 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) container_of(work, struct iwl_priv, bt_full_concurrency); struct iwl_rxon_context *ctx; - mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - goto out; + return; /* dont send host command if rf-kill is on */ if (!iwl_is_ready_rf(priv)) - goto out; + return; IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", priv->bt_full_concurrent ? @@ -507,15 +498,15 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) * LQ & RXON updated cmds must be sent before BT Config cmd * to avoid 3-wire collisions */ + mutex_lock(&priv->mutex); for_each_context(priv, ctx) { if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); iwlcore_commit_rxon(priv, ctx); } + mutex_unlock(&priv->mutex); priv->cfg->ops->hcmd->send_bt_config(priv); -out: - mutex_unlock(&priv->mutex); } /** @@ -565,7 +556,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, } /* Set starting address; reads will auto-increment */ - iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* @@ -573,13 +564,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { - data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event(priv, time, data, ev); } @@ -597,7 +588,10 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ - base = priv->device_pointers.error_event_table; + if (priv->ucode_type == UCODE_INIT) + base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); + else + base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { capacity = iwl_read_targ_mem(priv, base); num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); @@ -726,10 +720,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) /* If an RXB doesn't have a Rx queue slot associated with it, * then a bug has been introduced in the queue refilling * routines -- catch it here */ - if (WARN_ON(rxb == NULL)) { - i = (i + 1) & RX_QUEUE_MASK; - continue; - } + BUG_ON(rxb == NULL); rxq->queue[i] = NULL; @@ -769,7 +760,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) if (w->cmd == pkt->hdr.cmd) { w->triggered = true; if (w->fn) - w->fn(priv, pkt, w->fn_data); + w->fn(priv, pkt); } } spin_unlock(&priv->_agn.notif_wait_lock); @@ -846,6 +837,199 @@ static void iwl_rx_handle(struct iwl_priv *priv) iwlagn_rx_queue_restock(priv); } +/* call this function to flush any scheduled tasklet */ +static inline void iwl_synchronize_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->pci_dev->irq); + tasklet_kill(&priv->irq_tasklet); +} + +static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) +{ + u32 inta, handled = 0; + u32 inta_fh; + unsigned long flags; + u32 i; +#ifdef CONFIG_IWLWIFI_DEBUG + u32 inta_mask; +#endif + + spin_lock_irqsave(&priv->lock, flags); + + /* Ack/clear/reset pending uCode interrupts. + * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, + * and will clear only when CSR_FH_INT_STATUS gets cleared. */ + inta = iwl_read32(priv, CSR_INT); + iwl_write32(priv, CSR_INT, inta); + + /* Ack/clear/reset pending flow-handler (DMA) interrupts. + * Any new interrupts that happen after this, either while we're + * in this tasklet, or later, will show up in next ISR/tasklet. */ + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & IWL_DL_ISR) { + /* just for debug */ + inta_mask = iwl_read32(priv, CSR_INT_MASK); + IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + inta, inta_mask, inta_fh); + } +#endif + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not + * atomic, make sure that inta covers all the interrupts that + * we've discovered, even if FH interrupt came in just after + * reading CSR_INT. */ + if (inta_fh & CSR49_FH_INT_RX_MASK) + inta |= CSR_INT_BIT_FH_RX; + if (inta_fh & CSR49_FH_INT_TX_MASK) + inta |= CSR_INT_BIT_FH_TX; + + /* Now service all interrupt bits discovered above. */ + if (inta & CSR_INT_BIT_HW_ERR) { + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); + + /* Tell the device to stop sending interrupts */ + iwl_disable_interrupts(priv); + + priv->isr_stats.hw++; + iwl_irq_handle_error(priv); + + handled |= CSR_INT_BIT_HW_ERR; + + return; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + /* NIC fires this, but we don't use it, redundant with WAKEUP */ + if (inta & CSR_INT_BIT_SCD) { + IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " + "the frame/frames.\n"); + priv->isr_stats.sch++; + } + + /* Alive notification via Rx interrupt will do the real work */ + if (inta & CSR_INT_BIT_ALIVE) { + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } + } +#endif + /* Safely ignore these bits for debug checks below */ + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); + + /* HW RF KILL switch toggled */ + if (inta & CSR_INT_BIT_RF_KILL) { + int hw_rf_kill = 0; + if (!(iwl_read32(priv, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) + hw_rf_kill = 1; + + IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", + hw_rf_kill ? "disable radio" : "enable radio"); + + priv->isr_stats.rfkill++; + + /* driver only loads ucode once setting the interface up. + * the driver allows loading the ucode even if the radio + * is killed. Hence update the killswitch state here. The + * rfkill handler will care about restarting if needed. + */ + if (!test_bit(STATUS_ALIVE, &priv->status)) { + if (hw_rf_kill) + set_bit(STATUS_RF_KILL_HW, &priv->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->status); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); + } + + handled |= CSR_INT_BIT_RF_KILL; + } + + /* Chip got too hot and stopped itself */ + if (inta & CSR_INT_BIT_CT_KILL) { + IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; + handled |= CSR_INT_BIT_CT_KILL; + } + + /* Error detected by uCode */ + if (inta & CSR_INT_BIT_SW_ERR) { + IWL_ERR(priv, "Microcode SW error detected. " + " Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + iwl_irq_handle_error(priv); + handled |= CSR_INT_BIT_SW_ERR; + } + + /* + * uCode wakes up after power-down sleep. + * Tell device about any new tx or host commands enqueued, + * and about any Rx buffers made available while asleep. + */ + if (inta & CSR_INT_BIT_WAKEUP) { + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); + iwl_rx_queue_update_write_ptr(priv, &priv->rxq); + for (i = 0; i < priv->hw_params.max_txq_num; i++) + iwl_txq_update_write_ptr(priv, &priv->txq[i]); + priv->isr_stats.wakeup++; + handled |= CSR_INT_BIT_WAKEUP; + } + + /* All uCode command responses, including Tx command responses, + * Rx "responses" (frame-received notification), and other + * notifications from uCode come through here*/ + if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { + iwl_rx_handle(priv); + priv->isr_stats.rx++; + handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); + } + + /* This "Tx" DMA channel is used only for loading uCode */ + if (inta & CSR_INT_BIT_FH_TX) { + IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); + priv->isr_stats.tx++; + handled |= CSR_INT_BIT_FH_TX; + /* Wake up uCode load routine, now that load is complete */ + priv->ucode_write_complete = 1; + wake_up_interruptible(&priv->wait_command_queue); + } + + if (inta & ~handled) { + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } + + if (inta & ~(priv->inta_mask)) { + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", + inta & ~priv->inta_mask); + IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); + } + + /* Re-enable all interrupts */ + /* only Re-enable if disabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); + /* Re-enable RF_KILL if it occurred */ + else if (handled & CSR_INT_BIT_RF_KILL) + iwl_enable_rfkill_int(priv); + +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + inta = iwl_read32(priv, CSR_INT); + inta_mask = iwl_read32(priv, CSR_INT_MASK); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " + "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); + } +#endif +} + /* tasklet for iwlagn interrupt */ static void iwl_irq_tasklet(struct iwl_priv *priv) { @@ -987,7 +1171,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); iwl_write32(priv, CSR_FH_INT_STATUS, - CSR_FH_INT_RX_MASK); + CSR49_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; @@ -1025,7 +1209,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; @@ -1173,48 +1357,26 @@ static struct attribute_group iwl_attribute_group = { * ******************************************************************************/ -static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) -{ - if (desc->v_addr) - dma_free_coherent(&pci_dev->dev, desc->len, - desc->v_addr, desc->p_addr); - desc->v_addr = NULL; - desc->len = 0; -} - -static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img) -{ - iwl_free_fw_desc(pci_dev, &img->code); - iwl_free_fw_desc(pci_dev, &img->data); -} - -static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc, - const void *data, size_t len) +static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) { - if (!len) { - desc->v_addr = NULL; - return -EINVAL; - } - - desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len, - &desc->p_addr, GFP_KERNEL); - if (!desc->v_addr) - return -ENOMEM; - desc->len = len; - memcpy(desc->v_addr, data, len); - return 0; + iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); + iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); + iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); + iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); + iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); + iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); } -static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) +static void iwl_nic_start(struct iwl_priv *priv) { - iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt); - iwl_free_fw_img(priv->pci_dev, &priv->ucode_init); + /* Remove all resets to allow NIC to operate */ + iwl_write32(priv, CSR_RESET, 0); } struct iwlagn_ucode_capabilities { u32 max_probe_length; u32 standard_phy_calibration_size; - u32 flags; + bool pan; }; static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); @@ -1260,8 +1422,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) } struct iwlagn_firmware_pieces { - const void *inst, *data, *init, *init_data; - size_t inst_size, data_size, init_size, init_data_size; + const void *inst, *data, *init, *init_data, *boot; + size_t inst_size, data_size, init_size, init_data_size, boot_size; u32 build; @@ -1282,18 +1444,28 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, switch (api_ver) { default: - hdr_size = 28; - if (ucode_raw->size < hdr_size) { - IWL_ERR(priv, "File size too small!\n"); - return -EINVAL; + /* + * 4965 doesn't revision the firmware file format + * along with the API version, it always uses v1 + * file format. + */ + if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != + CSR_HW_REV_TYPE_4965) { + hdr_size = 28; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + return -EINVAL; + } + pieces->build = le32_to_cpu(ucode->u.v2.build); + pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); + pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); + pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); + src = ucode->u.v2.data; + break; } - pieces->build = le32_to_cpu(ucode->u.v2.build); - pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); - pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); - src = ucode->u.v2.data; - break; + /* fall through for 4965 */ case 0: case 1: case 2: @@ -1307,6 +1479,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); + pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size); src = ucode->u.v1.data; break; } @@ -1314,7 +1487,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, /* Verify size of file vs. image size info in file's header */ if (ucode_raw->size != hdr_size + pieces->inst_size + pieces->data_size + pieces->init_size + - pieces->init_data_size) { + pieces->init_data_size + pieces->boot_size) { IWL_ERR(priv, "uCode file size %d does not match expected size\n", @@ -1330,6 +1503,8 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, src += pieces->init_size; pieces->init_data = src; src += pieces->init_data_size; + pieces->boot = src; + src += pieces->boot_size; return 0; } @@ -1430,7 +1605,8 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, pieces->init_data_size = tlv_len; break; case IWL_UCODE_TLV_BOOT: - IWL_ERR(priv, "Found unexpected BOOT ucode\n"); + pieces->boot = tlv_data; + pieces->boot_size = tlv_len; break; case IWL_UCODE_TLV_PROBE_MAX_LEN: if (tlv_len != sizeof(u32)) @@ -1441,23 +1617,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, case IWL_UCODE_TLV_PAN: if (tlv_len) goto invalid_tlv_len; - capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; - break; - case IWL_UCODE_TLV_FLAGS: - /* must be at least one u32 */ - if (tlv_len < sizeof(u32)) - goto invalid_tlv_len; - /* and a proper number of u32s */ - if (tlv_len % sizeof(u32)) - goto invalid_tlv_len; - /* - * This driver only reads the first u32 as - * right now no more features are defined, - * if that changes then either the driver - * will not work with the new firmware, or - * it'll not take advantage of new features. - */ - capa->flags = le32_to_cpup((__le32 *)tlv_data); + capa->pan = true; break; case IWL_UCODE_TLV_INIT_EVTLOG_PTR: if (tlv_len != sizeof(u32)) @@ -1507,7 +1667,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, le32_to_cpup((__le32 *)tlv_data); break; default: - IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type); + IWL_WARN(priv, "unknown TLV: %d\n", tlv_type); break; } } @@ -1646,6 +1806,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.init_size); IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", pieces.init_data_size); + IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n", + pieces.boot_size); /* Verify that uCode images will fit in card's SRAM */ if (pieces.inst_size > priv->hw_params.max_inst_size) { @@ -1672,25 +1834,48 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) goto try_again; } + if (pieces.boot_size > priv->hw_params.max_bsm_size) { + IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n", + pieces.boot_size); + goto try_again; + } + /* Allocate ucode buffers for card's bus-master loading ... */ /* Runtime instructions and 2 copies of data: * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ - if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code, - pieces.inst, pieces.inst_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data, - pieces.data, pieces.data_size)) + priv->ucode_code.len = pieces.inst_size; + iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); + + priv->ucode_data.len = pieces.data_size; + iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); + + priv->ucode_data_backup.len = pieces.data_size; + iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); + + if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || + !priv->ucode_data_backup.v_addr) goto err_pci_alloc; /* Initialization instructions and data */ if (pieces.init_size && pieces.init_data_size) { - if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code, - pieces.init, pieces.init_size)) + priv->ucode_init.len = pieces.init_size; + iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); + + priv->ucode_init_data.len = pieces.init_data_size; + iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); + + if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) goto err_pci_alloc; - if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data, - pieces.init_data, pieces.init_data_size)) + } + + /* Bootstrap (instructions only, no data) */ + if (pieces.boot_size) { + priv->ucode_boot.len = pieces.boot_size; + iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); + + if (!priv->ucode_boot.v_addr) goto err_pci_alloc; } @@ -1716,16 +1901,50 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) priv->cfg->base_params->max_event_log_size; priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; - if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { + if (ucode_capa.pan) { priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; } else priv->sta_key_max_num = STA_KEY_MAX_NUM; - if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) - priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; - else - priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + /* Copy images into buffers for card's bus-master reads ... */ + + /* Runtime instructions (first block of data in file) */ + IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", + pieces.inst_size); + memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); + + IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", + priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); + + /* + * Runtime data + * NOTE: Copy into backup buffer will be done in iwl_up() + */ + IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", + pieces.data_size); + memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); + memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size); + + /* Initialization instructions */ + if (pieces.init_size) { + IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", + pieces.init_size); + memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); + } + + /* Initialization data */ + if (pieces.init_data_size) { + IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", + pieces.init_data_size); + memcpy(priv->ucode_init_data.v_addr, pieces.init_data, + pieces.init_data_size); + } + + /* Bootstrap instructions */ + IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", + pieces.boot_size); + memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); /* * figure out the offset of chain noise reset and gain commands @@ -1857,13 +2076,13 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; u32 pc, hcmd; - struct iwl_error_event_table table; - base = priv->device_pointers.error_event_table; - if (priv->ucode_type == UCODE_SUBTYPE_INIT) { + if (priv->ucode_type == UCODE_INIT) { + base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); if (!base) base = priv->_agn.init_errlog_ptr; } else { + base = le32_to_cpu(priv->card_alive.error_event_table_ptr); if (!base) base = priv->_agn.inst_errlog_ptr; } @@ -1871,15 +2090,11 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Not valid error log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == UCODE_SUBTYPE_INIT) - ? "Init" : "RT"); + base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); return; } - iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); - - count = table.valid; + count = iwl_read_targ_mem(priv, base); if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERR(priv, "Start IWL Error Log Dump:\n"); @@ -1887,18 +2102,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) priv->status, count); } - desc = table.error_id; + desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); priv->isr_stats.err_code = desc; - pc = table.pc; - blink1 = table.blink1; - blink2 = table.blink2; - ilink1 = table.ilink1; - ilink2 = table.ilink2; - data1 = table.data1; - data2 = table.data2; - line = table.line; - time = table.tsf_low; - hcmd = table.hcmd; + pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); + blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); + blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); + ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); + ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); + data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); + data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); + line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); + time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); + hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, blink1, blink2, ilink1, ilink2); @@ -1932,11 +2147,12 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, if (num_events == 0) return pos; - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == UCODE_SUBTYPE_INIT) { + if (priv->ucode_type == UCODE_INIT) { + base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); if (!base) base = priv->_agn.init_evtlog_ptr; } else { + base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!base) base = priv->_agn.inst_evtlog_ptr; } @@ -1953,14 +2169,14 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, iwl_grab_nic_access(priv); /* Set starting address; reads will auto-increment */ - iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ if (bufsz) { @@ -1974,7 +2190,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, time, ev); } } else { - data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (bufsz) { pos += scnprintf(*buf + pos, bufsz - pos, "EVT_LOGT:%010u:0x%08x:%04u\n", @@ -2045,12 +2261,13 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, int pos = 0; size_t bufsz = 0; - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == UCODE_SUBTYPE_INIT) { + if (priv->ucode_type == UCODE_INIT) { + base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); logsize = priv->_agn.init_evtlog_size; if (!base) base = priv->_agn.init_evtlog_ptr; } else { + base = le32_to_cpu(priv->card_alive.log_event_table_ptr); logsize = priv->_agn.inst_evtlog_size; if (!base) base = priv->_agn.inst_evtlog_ptr; @@ -2059,9 +2276,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Invalid event log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == UCODE_SUBTYPE_INIT) - ? "Init" : "RT"); + base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); return -EINVAL; } @@ -2208,15 +2423,31 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) * from protocol/runtime uCode (initialization uCode's * Alive gets handled by iwl_init_alive_start()). */ -static int iwl_alive_start(struct iwl_priv *priv) +static void iwl_alive_start(struct iwl_priv *priv) { int ret = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - iwl_reset_ict(priv); - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); + /* Initialize uCode has loaded Runtime uCode ... verify inst image. + * This is a paranoid check, because we would not have gotten the + * "runtime" alive if code weren't properly loaded. */ + if (iwl_verify_ucode(priv)) { + /* Runtime instruction load was bad; + * take it all the way back down so we can try again */ + IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); + goto restart; + } + + ret = priv->cfg->ops->lib->alive_notify(priv); + if (ret) { + IWL_WARN(priv, + "Could not complete ALIVE transition [ntf]: %d\n", ret); + goto restart; + } + + /* After the ALIVE response, we can send host commands to the uCode */ set_bit(STATUS_ALIVE, &priv->status); @@ -2224,7 +2455,7 @@ static int iwl_alive_start(struct iwl_priv *priv) iwl_setup_watchdog(priv); if (iwl_is_rfkill(priv)) - return -ERFKILL; + return; /* download priority table before any calibration request */ if (priv->cfg->bt_params && @@ -2238,14 +2469,10 @@ static int iwl_alive_start(struct iwl_priv *priv) iwlagn_send_prio_tbl(priv); /* FIXME: w/a to force change uCode BT state machine */ - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); - if (ret) - return ret; - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); - if (ret) - return ret; + iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); } if (priv->hw_params.calib_rt_cfg) iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); @@ -2287,23 +2514,30 @@ static int iwl_alive_start(struct iwl_priv *priv) set_bit(STATUS_READY, &priv->status); /* Configure the adapter for unassociated operation */ - ret = iwlcore_commit_rxon(priv, ctx); - if (ret) - return ret; + iwlcore_commit_rxon(priv, ctx); /* At this point, the NIC is initialized and operational */ iwl_rf_kill_ct_config(priv); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); + wake_up_interruptible(&priv->wait_command_queue); - return iwl_power_update_mode(priv, true); + iwl_power_update_mode(priv, true); + IWL_DEBUG_INFO(priv, "Updated power mode\n"); + + + return; + + restart: + queue_work(priv->workqueue, &priv->restart); } static void iwl_cancel_deferred_work(struct iwl_priv *priv); static void __iwl_down(struct iwl_priv *priv) { - int exit_pending; + unsigned long flags; + int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); @@ -2329,15 +2563,40 @@ static void __iwl_down(struct iwl_priv *priv) priv->bt_full_concurrent = false; priv->bt_ci_compliance = 0; + /* Unblock any waiting calls */ + wake_up_interruptible_all(&priv->wait_command_queue); + /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) clear_bit(STATUS_EXIT_PENDING, &priv->status); + /* stop and reset the on-board processor */ + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + + /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + iwl_synchronize_irq(priv); + if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); - /* Clear out all status bits but a few that are stable across reset */ + /* If we have not previously called iwl_init() then + * clear all bits but the RF Kill bit and return */ + if (!iwl_is_init(priv)) { + priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << + STATUS_RF_KILL_HW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | + test_bit(STATUS_EXIT_PENDING, &priv->status) << + STATUS_EXIT_PENDING; + goto exit; + } + + /* ...otherwise clear out all the status bits but the RF Kill + * bit and continue taking the NIC down. */ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << @@ -2347,7 +2606,25 @@ static void __iwl_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - iwlagn_stop_device(priv); + /* device going down, Stop using ICT table */ + if (priv->cfg->ops->lib->isr_ops.disable) + priv->cfg->ops->lib->isr_ops.disable(priv); + + iwlagn_txq_ctx_stop(priv); + iwlagn_rxq_stop(priv); + + /* Power-down device's busmaster DMA clocks */ + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); + udelay(5); + + /* Make sure (redundant) we've released our request to stay awake */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + + /* Stop the device, and put it in low power state */ + iwl_apm_stop(priv); + + exit: + memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -2367,10 +2644,9 @@ static void iwl_down(struct iwl_priv *priv) #define HW_READY_TIMEOUT (50) -/* Note: returns poll_bit return value, which is >= 0 if success */ static int iwl_set_hw_ready(struct iwl_priv *priv) { - int ret; + int ret = 0; iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); @@ -2380,21 +2656,25 @@ static int iwl_set_hw_ready(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); + if (ret != -ETIMEDOUT) + priv->hw_ready = true; + else + priv->hw_ready = false; - IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); + IWL_DEBUG_INFO(priv, "hardware %s\n", + (priv->hw_ready == 1) ? "ready" : "not ready"); return ret; } -/* Note: returns standard 0/-ERROR code */ -int iwl_prepare_card_hw(struct iwl_priv *priv) +static int iwl_prepare_card_hw(struct iwl_priv *priv) { - int ret; + int ret = 0; IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); ret = iwl_set_hw_ready(priv); - if (ret >= 0) - return 0; + if (priv->hw_ready) + return ret; /* If HW is not ready, prepare the conditions to check again */ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, @@ -2404,13 +2684,10 @@ int iwl_prepare_card_hw(struct iwl_priv *priv) ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); - if (ret < 0) - return ret; - /* HW should be ready by now, check again. */ - ret = iwl_set_hw_ready(priv); - if (ret >= 0) - return 0; + if (ret != -ETIMEDOUT) + iwl_set_hw_ready(priv); + return ret; } @@ -2419,15 +2696,19 @@ int iwl_prepare_card_hw(struct iwl_priv *priv) static int __iwl_up(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; + int i; int ret; - lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } + if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { + IWL_ERR(priv, "ucode not available for device bringup\n"); + return -EIO; + } + for_each_context(priv, ctx) { ret = iwlagn_alloc_bcast_station(priv, ctx); if (ret) { @@ -2436,33 +2717,89 @@ static int __iwl_up(struct iwl_priv *priv) } } - ret = iwlagn_run_init_ucode(priv); - if (ret) { - IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); - goto error; + iwl_prepare_card_hw(priv); + + if (!priv->hw_ready) { + IWL_WARN(priv, "Exit HW not ready\n"); + return -EIO; + } + + /* If platform's RF_KILL switch is NOT set to KILL */ + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); + else + set_bit(STATUS_RF_KILL_HW, &priv->status); + + if (iwl_is_rfkill(priv)) { + wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); + + iwl_enable_interrupts(priv); + IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); + return 0; } - ret = iwlagn_load_ucode_wait_alive(priv, - &priv->ucode_rt, - UCODE_SUBTYPE_REGULAR, - UCODE_SUBTYPE_REGULAR_NEW); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + + /* must be initialised before iwl_hw_nic_init */ + if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) + priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + else + priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + + ret = iwlagn_hw_nic_init(priv); if (ret) { - IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); - goto error; + IWL_ERR(priv, "Unable to init nic\n"); + return ret; } - ret = iwl_alive_start(priv); - if (ret) - goto error; - return 0; + /* make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + + /* clear (again), then enable host interrupts */ + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); + + /* really make sure rfkill handshake bits are cleared */ + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + + /* Copy original ucode data image from disk into backup cache. + * This will be used to initialize the on-board processor's + * data SRAM for a clean start when the runtime program first loads. */ + memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, + priv->ucode_data.len); + + for (i = 0; i < MAX_HW_RESTARTS; i++) { + + /* load bootstrap state machine, + * load bootstrap program into processor's memory, + * prepare to load the "initialize" uCode */ + ret = priv->cfg->ops->lib->load_ucode(priv); + + if (ret) { + IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", + ret); + continue; + } + + /* start card; "initialize" will load runtime ucode */ + iwl_nic_start(priv); + + IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); + + return 0; + } - error: set_bit(STATUS_EXIT_PENDING, &priv->status); __iwl_down(priv); clear_bit(STATUS_EXIT_PENDING, &priv->status); - IWL_ERR(priv, "Unable to initialize device.\n"); - return ret; + /* tried to restart and config the device for as long as our + * patience could withstand */ + IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); + return -EIO; } @@ -2472,6 +2809,36 @@ static int __iwl_up(struct iwl_priv *priv) * *****************************************************************************/ +static void iwl_bg_init_alive_start(struct work_struct *data) +{ + struct iwl_priv *priv = + container_of(data, struct iwl_priv, init_alive_start.work); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + priv->cfg->ops->lib->init_alive_start(priv); + mutex_unlock(&priv->mutex); +} + +static void iwl_bg_alive_start(struct work_struct *data) +{ + struct iwl_priv *priv = + container_of(data, struct iwl_priv, alive_start.work); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + /* enable dram interrupt */ + if (priv->cfg->ops->lib->isr_ops.reset) + priv->cfg->ops->lib->isr_ops.reset(priv); + + mutex_lock(&priv->mutex); + iwl_alive_start(priv); + mutex_unlock(&priv->mutex); +} + static void iwl_bg_run_time_calib_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, @@ -2486,8 +2853,17 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) } if (priv->start_calib) { - iwl_chain_noise_calibration(priv); - iwl_sensitivity_calibration(priv); + if (iwl_bt_statistics(priv)) { + iwl_chain_noise_calibration(priv, + (void *)&priv->_agn.statistics_bt); + iwl_sensitivity_calibration(priv, + (void *)&priv->_agn.statistics_bt); + } else { + iwl_chain_noise_calibration(priv, + (void *)&priv->_agn.statistics); + iwl_sensitivity_calibration(priv, + (void *)&priv->_agn.statistics); + } } mutex_unlock(&priv->mutex); @@ -2537,7 +2913,14 @@ static void iwl_bg_restart(struct work_struct *data) iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { - WARN_ON(1); + iwl_down(priv); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + __iwl_up(priv); + mutex_unlock(&priv->mutex); } } @@ -2648,6 +3031,8 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw) * *****************************************************************************/ +#define UCODE_READY_TIMEOUT (4 * HZ) + /* * Not a mac80211 entry point function, but it fits in with all the * other mac80211 functions grouped here. @@ -2670,16 +3055,14 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + if (!priv->cfg->base_params->broken_powersave) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; if (priv->cfg->sku & IWL_SKU_N) hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | IEEE80211_HW_SUPPORTS_STATIC_SMPS; - if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) - hw->flags |= IEEE80211_HW_MFP_CAPABLE; - hw->sta_data_size = sizeof(struct iwl_station_priv); hw->vif_data_size = sizeof(struct iwl_vif_priv); @@ -2729,7 +3112,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, } -static int iwlagn_mac_start(struct ieee80211_hw *hw) +int iwlagn_mac_start(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; int ret; @@ -2740,23 +3123,37 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); ret = __iwl_up(priv); mutex_unlock(&priv->mutex); + if (ret) return ret; + if (iwl_is_rfkill(priv)) + goto out; + IWL_DEBUG_INFO(priv, "Start UP work done.\n"); - /* Now we should be done, and the READY bit should be set. */ - if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) - ret = -EIO; + /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from + * mac80211 will not be run successfully. */ + ret = wait_event_interruptible_timeout(priv->wait_command_queue, + test_bit(STATUS_READY, &priv->status), + UCODE_READY_TIMEOUT); + if (!ret) { + if (!test_bit(STATUS_READY, &priv->status)) { + IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", + jiffies_to_msecs(UCODE_READY_TIMEOUT)); + return -ETIMEDOUT; + } + } iwlagn_led_enable(priv); +out: priv->is_open = 1; IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } -static void iwlagn_mac_stop(struct ieee80211_hw *hw) +void iwlagn_mac_stop(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; @@ -2779,7 +3176,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "leave\n"); } -static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; @@ -2794,11 +3191,11 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MACDUMP(priv, "leave\n"); } -static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, - u32 iv32, u16 *phase1key) +void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -2811,10 +3208,9 @@ static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); } -static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) +int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; @@ -2889,11 +3285,11 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) +int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size) { struct iwl_priv *priv = hw->priv; int ret = -EINVAL; @@ -2952,10 +3348,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, } break; case IEEE80211_AMPDU_TX_OPERATIONAL: - buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - - iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size); - /* * If the limit is 0, then it wasn't initialised yet, * use the default. We can do that since we take the @@ -3000,9 +3392,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, return ret; } -static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; @@ -3043,8 +3435,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return 0; } -static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_channel_switch *ch_switch) +void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch) { struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; @@ -3065,22 +3457,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->mutex); - if (iwl_is_rfkill(priv)) - goto out; + goto out_exit; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || test_bit(STATUS_SCANNING, &priv->status)) - goto out; + goto out_exit; if (!iwl_is_associated_ctx(ctx)) - goto out; + goto out_exit; /* channel switch in progress */ if (priv->switch_rxon.switch_in_progress == true) - goto out; + goto out_exit; + mutex_lock(&priv->mutex); if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -3136,15 +3527,16 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, } out: mutex_unlock(&priv->mutex); +out_exit: if (!priv->switch_rxon.switch_in_progress) ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); } -static void iwlagn_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) +void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) { struct iwl_priv *priv = hw->priv; __le32 filter_or = 0, filter_nand = 0; @@ -3191,7 +3583,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; } -static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) +void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; @@ -3337,6 +3729,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); + INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); + INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); iwl_setup_scan_deferred_work(priv); @@ -3356,8 +3750,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) priv->watchdog.data = (unsigned long)priv; priv->watchdog.function = iwl_bg_watchdog; - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); + if (!priv->cfg->base_params->use_isr_legacy) + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); + else + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet_legacy, (unsigned long)priv); } static void iwl_cancel_deferred_work(struct iwl_priv *priv) @@ -3365,6 +3763,8 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) if (priv->cfg->ops->lib->cancel_deferred_work) priv->cfg->ops->lib->cancel_deferred_work(priv); + cancel_delayed_work_sync(&priv->init_alive_start); + cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); @@ -3408,6 +3808,7 @@ static int iwl_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); + mutex_init(&priv->sync_cmd_mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; @@ -3506,13 +3907,12 @@ struct ieee80211_ops iwlagn_hw_ops = { .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, }; -static u32 iwl_hw_detect(struct iwl_priv *priv) +static void iwl_hw_detect(struct iwl_priv *priv) { - u8 rev_id; - - pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); - IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); - return iwl_read32(priv, CSR_HW_REV); + priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); + priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); + priv->rev_id = priv->pci_dev->revision; + IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); } static int iwl_set_hw_params(struct iwl_priv *priv) @@ -3555,28 +3955,6 @@ static const u8 iwlagn_pan_ac_to_queue[] = { 7, 6, 5, 4, }; -/* This function both allocates and initializes hw and priv. */ -static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) -{ - struct iwl_priv *priv; - /* mac80211 allocates memory for this device instance, including - * space for this driver's private structure */ - struct ieee80211_hw *hw; - - hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops); - if (hw == NULL) { - pr_err("%s: Can not allocate network device\n", - cfg->name); - goto out; - } - - priv = hw->priv; - priv->hw = hw; - -out: - return hw; -} - static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0, i; @@ -3585,12 +3963,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; u16 pci_cmd, num_mac; - u32 hw_rev; /************************ * 1. Allocating HW data ************************/ + /* Disabling hardware scan means that mac80211 will perform scans + * "the hard way", rather than using device's scan. */ + if (cfg->mod_params->disable_hw_scan) { + dev_printk(KERN_DEBUG, &(pdev->dev), + "sw scan support is deprecated\n"); + iwlagn_hw_ops.hw_scan = NULL; + } + hw = iwl_alloc_all(cfg); if (!hw) { err = -ENOMEM; @@ -3599,8 +3984,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv = hw->priv; /* At this point both hw and priv are allocated. */ - priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED; - /* * The default context is always valid, * more may be discovered when firmware @@ -3733,15 +4116,16 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - hw_rev = iwl_hw_detect(priv); + iwl_hw_detect(priv); IWL_INFO(priv, "Detected %s, REV=0x%X\n", - priv->cfg->name, hw_rev); + priv->cfg->name, priv->hw_rev); /* We disable the RETRY_TIMEOUT register (0x41) to keep * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - if (iwl_prepare_card_hw(priv)) { + iwl_prepare_card_hw(priv); + if (!priv->hw_ready) { IWL_WARN(priv, "Failed, HW not ready\n"); goto out_iounmap; } @@ -3750,7 +4134,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 4. Read EEPROM *****************/ /* Read the EEPROM */ - err = iwl_eeprom_init(priv, hw_rev); + err = iwl_eeprom_init(priv); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_iounmap; @@ -3802,9 +4186,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_enable_msi(priv->pci_dev); - iwl_alloc_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.alloc) + priv->cfg->ops->lib->isr_ops.alloc(priv); - err = request_irq(priv->pci_dev->irq, iwl_isr_ict, + err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, IRQF_SHARED, DRV_NAME, priv); if (err) { IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); @@ -3851,7 +4236,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; free_irq(priv->pci_dev->irq, priv); - iwl_free_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.free) + priv->cfg->ops->lib->isr_ops.free(priv); out_disable_msi: pci_disable_msi(priv->pci_dev); iwl_uninit_drv(priv); @@ -3897,9 +4283,17 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); priv->mac80211_registered = 0; + } else { + iwl_down(priv); } - /* Reset to low power before unloading driver. */ + /* + * Make sure device is reset to low power before unloading driver. + * This may be redundant with iwl_down(), but there are paths to + * run iwl_down() without calling apm_ops.stop(), and there are + * paths to avoid running iwl_down() at all before leaving driver. + * This (inexpensive) call *makes sure* device is reset. + */ iwl_apm_stop(priv); iwl_tt_exit(priv); @@ -3941,7 +4335,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_uninit_drv(priv); - iwl_free_isr_ict(priv); + if (priv->cfg->ops->lib->isr_ops.free) + priv->cfg->ops->lib->isr_ops.free(priv); dev_kfree_skb(priv->beacon_skb); @@ -4190,21 +4585,43 @@ module_exit(iwl_exit); module_init(iwl_init); #ifdef CONFIG_IWLWIFI_DEBUG +module_param_named(debug50, iwl_debug_level, uint, S_IRUGO); +MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); #endif +module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); +MODULE_PARM_DESC(swcrypto50, + "using crypto in software (default 0 [hardware]) (deprecated)"); module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); +module_param_named(queues_num50, + iwlagn_mod_params.num_of_queues, int, S_IRUGO); +MODULE_PARM_DESC(queues_num50, + "number of hw queues in 50xx series (deprecated)"); module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); MODULE_PARM_DESC(queues_num, "number of hw queues."); +module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); +MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); +module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, + int, S_IRUGO); +MODULE_PARM_DESC(amsdu_size_8K50, + "enable 8K amsdu size in 50XX series (deprecated)"); module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, int, S_IRUGO); MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); +module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); +MODULE_PARM_DESC(fw_restart50, + "restart firmware in case of error (deprecated)"); module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); +module_param_named( + disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); +MODULE_PARM_DESC(disable_hw_scan, + "disable hardware scanning (default 0) (deprecated)"); module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, S_IRUGO); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h index c475ac427596..20f8e4188994 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,6 +66,7 @@ #include "iwl-dev.h" /* configuration for the _agn devices */ +extern struct iwl_cfg iwl4965_agn_cfg; extern struct iwl_cfg iwl5300_agn_cfg; extern struct iwl_cfg iwl5100_agn_cfg; extern struct iwl_cfg iwl5350_agn_cfg; @@ -113,6 +114,7 @@ extern struct iwl_hcmd_ops iwlagn_bt_hcmd; extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; extern struct ieee80211_ops iwlagn_hw_ops; +extern struct ieee80211_ops iwl4965_hw_ops; int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); @@ -120,19 +122,6 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->pci_dev->irq); - tasklet_kill(&priv->irq_tasklet); -} - -int iwl_prepare_card_hw(struct iwl_priv *priv); - -int iwlagn_start_device(struct iwl_priv *priv); -void iwlagn_stop_device(struct iwl_priv *priv); - /* tx queue */ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index); @@ -144,6 +133,10 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, u16 byte_cnt); void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq); +int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, + int tx_fifo, int sta_id, int tid, u16 ssn_idx); +int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); @@ -158,14 +151,16 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, u32 changes); /* uCode */ +int iwlagn_load_ucode(struct iwl_priv *priv); void iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); +void iwlagn_rx_calib_complete(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +void iwlagn_init_alive_start(struct iwl_priv *priv); +int iwlagn_alive_notify(struct iwl_priv *priv); +int iwl_verify_ucode(struct iwl_priv *priv); +void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); void iwlagn_send_prio_tbl(struct iwl_priv *priv); -int iwlagn_run_init_ucode(struct iwl_priv *priv); -int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, - struct fw_img *image, - int subtype, int alternate_subtype); /* lib */ void iwl_check_abort_status(struct iwl_priv *priv, @@ -184,6 +179,8 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv); int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); +void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); /* rx */ void iwlagn_rx_queue_restock(struct iwl_priv *priv); @@ -209,9 +206,6 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); -void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, - struct ieee80211_sta *sta, - int tid, int frame_limit); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, @@ -231,7 +225,6 @@ static inline u32 iwl_tx_status_to_mac80211(u32 status) case TX_STATUS_DIRECT_DONE: return IEEE80211_TX_STAT_ACK; case TX_STATUS_FAIL_DEST_PS: - case TX_STATUS_FAIL_PASSIVE_NO_RX: return IEEE80211_TX_STAT_TX_FILTERED; default: return 0; @@ -318,7 +311,7 @@ static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) { - return le32_to_cpu(rate_n_flags) & RATE_MCS_RATE_MSK; + return le32_to_cpu(rate_n_flags) & 0xFF; } static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) @@ -336,12 +329,10 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); void __acquires(wait_entry) iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, - u8 cmd, void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data); -int __must_check __releases(wait_entry) + struct iwl_rx_packet *pkt), + u8 cmd); +signed long __releases(wait_entry) iwlagn_wait_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, unsigned long timeout); @@ -349,4 +340,32 @@ void __releases(wait_entry) iwlagn_remove_notification(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry); +/* mac80211 handlers (for 4965) */ +void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +int iwlagn_mac_start(struct ieee80211_hw *hw); +void iwlagn_mac_stop(struct ieee80211_hw *hw); +void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast); +int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key); +int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size); +int iwlagn_mac_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_channel_switch *ch_switch); +void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); + #endif /* __iwl_agn_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h index e125896c8096..ca42ffa63ed7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -103,7 +103,9 @@ enum { REPLY_WEPKEY = 0x20, /* RX, TX, LEDs */ + REPLY_3945_RX = 0x1b, /* 3945 only */ REPLY_TX = 0x1c, + REPLY_RATE_SCALE = 0x47, /* 3945 only */ REPLY_LEDS_CMD = 0x48, REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ @@ -227,7 +229,7 @@ struct iwl_cmd_header { * There is one exception: uCode sets bit 15 when it originates * the response/notification, i.e. when the response/notification * is not a direct response to a command sent by the driver. For - * example, uCode issues REPLY_RX when it sends a received frame + * example, uCode issues REPLY_3945_RX when it sends a received frame * to the driver; it is not a direct response to any driver command. * * The Linux driver uses the following format: @@ -246,6 +248,36 @@ struct iwl_cmd_header { } __packed; +/** + * struct iwl3945_tx_power + * + * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH + * + * Each entry contains two values: + * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained + * linear value that multiplies the output of the digital signal processor, + * before being sent to the analog radio. + * 2) Radio gain. This sets the analog gain of the radio Tx path. + * It is a coarser setting, and behaves in a logarithmic (dB) fashion. + * + * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. + */ +struct iwl3945_tx_power { + u8 tx_gain; /* gain for analog radio */ + u8 dsp_atten; /* gain for DSP */ +} __packed; + +/** + * struct iwl3945_power_per_rate + * + * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + */ +struct iwl3945_power_per_rate { + u8 rate; /* plcp */ + struct iwl3945_tx_power tpc; + u8 reserved; +} __packed; + /** * iwlagn rate_n_flags bit fields * @@ -292,8 +324,6 @@ struct iwl_cmd_header { #define RATE_MCS_SPATIAL_MSK 0x18 #define RATE_MCS_HT_DUP_POS 5 #define RATE_MCS_HT_DUP_MSK 0x20 -/* Both legacy and HT use bits 7:0 as the CCK/OFDM rate or HT MCS */ -#define RATE_MCS_RATE_MSK 0xff /* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */ #define RATE_MCS_FLAGS_POS 8 @@ -344,6 +374,30 @@ struct iwl_cmd_header { #define IWL_PWR_NUM_HT_OFDM_ENTRIES 24 #define IWL_PWR_CCK_ENTRIES 2 +/** + * union iwl4965_tx_power_dual_stream + * + * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + * Use __le32 version (struct tx_power_dual_stream) when building command. + * + * Driver provides radio gain and DSP attenuation settings to device in pairs, + * one value for each transmitter chain. The first value is for transmitter A, + * second for transmitter B. + * + * For SISO bit rates, both values in a pair should be identical. + * For MIMO rates, one value may be different from the other, + * in order to balance the Tx output between the two transmitters. + * + * See more details in doc for TXPOWER in iwl-4965-hw.h. + */ +union iwl4965_tx_power_dual_stream { + struct { + u8 radio_tx_gain[2]; + u8 dsp_predis_atten[2]; + } s; + u32 dw; +}; + /** * struct tx_power_dual_stream * @@ -355,6 +409,15 @@ struct tx_power_dual_stream { __le32 dw; } __packed; +/** + * struct iwl4965_tx_power_db + * + * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + */ +struct iwl4965_tx_power_db { + struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; +} __packed; + /** * Command REPLY_TX_POWER_DBM_CMD = 0x98 * struct iwlagn_tx_power_dbm_cmd @@ -386,18 +449,55 @@ struct iwl_tx_ant_config_cmd { *****************************************************************************/ #define UCODE_VALID_OK cpu_to_le32(0x1) +#define INITIALIZE_SUBTYPE (9) -enum iwlagn_ucode_subtype { - UCODE_SUBTYPE_REGULAR = 0, - UCODE_SUBTYPE_REGULAR_NEW = 1, - UCODE_SUBTYPE_INIT = 9, +/* + * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) + * + * uCode issues this "initialize alive" notification once the initialization + * uCode image has completed its work, and is ready to load the runtime image. + * This is the *first* "alive" notification that the driver will receive after + * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. + * + * See comments documenting "BSM" (bootstrap state machine). + * + * For 4965, this notification contains important calibration data for + * calculating txpower settings: + * + * 1) Power supply voltage indication. The voltage sensor outputs higher + * values for lower voltage, and vice verse. + * + * 2) Temperature measurement parameters, for each of two channel widths + * (20 MHz and 40 MHz) supported by the radios. Temperature sensing + * is done via one of the receiver chains, and channel width influences + * the results. + * + * 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation, + * for each of 5 frequency ranges. + */ +struct iwl_init_alive_resp { + u8 ucode_minor; + u8 ucode_major; + __le16 reserved1; + u8 sw_rev[8]; + u8 ver_type; + u8 ver_subtype; /* "9" for initialize alive */ + __le16 reserved2; + __le32 log_event_table_ptr; + __le32 error_event_table_ptr; + __le32 timestamp; + __le32 is_valid; + + /* calibration values from "initialize" uCode */ + __le32 voltage; /* signed, higher value is lower voltage */ + __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for HT40 */ + __le32 therm_r2[2]; /* signed */ + __le32 therm_r3[2]; /* signed */ + __le32 therm_r4[2]; /* signed */ + __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, + * 2 Tx chains */ +} __packed; - /* - * Not a valid subtype, the ucode has just a u8, so - * we can use something > 0xff for this value. - */ - UCODE_SUBTYPE_NONE_LOADED = 0x100, -}; /** * REPLY_ALIVE = 0x1 (response only, not a command) @@ -433,61 +533,49 @@ enum iwlagn_ucode_subtype { * * 2) error_event_table_ptr indicates base of the error log. This contains * information about any uCode error that occurs. For agn, the format - * of the error log is defined by struct iwl_error_event_table. + * of the error log is: + * + * __le32 valid; (nonzero) valid, (0) log is empty + * __le32 error_id; type of error + * __le32 pc; program counter + * __le32 blink1; branch link + * __le32 blink2; branch link + * __le32 ilink1; interrupt link + * __le32 ilink2; interrupt link + * __le32 data1; error-specific data + * __le32 data2; error-specific data + * __le32 line; source code line of error + * __le32 bcon_time; beacon timer + * __le32 tsf_low; network timestamp function timer + * __le32 tsf_hi; network timestamp function timer + * __le32 gp1; GP1 timer register + * __le32 gp2; GP2 timer register + * __le32 gp3; GP3 timer register + * __le32 ucode_ver; uCode version + * __le32 hw_ver; HW Silicon version + * __le32 brd_ver; HW board version + * __le32 log_pc; log program counter + * __le32 frame_ptr; frame pointer + * __le32 stack_ptr; stack pointer + * __le32 hcmd; last host command + * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag + * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag + * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag + * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag + * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt + * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT + * __le32 wait_event; wait event() caller address + * __le32 l2p_control; L2pControlField + * __le32 l2p_duration; L2pDurationField + * __le32 l2p_mhvalid; L2pMhValidBits + * __le32 l2p_addr_match; L2pAddrMatchStat + * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) + * __le32 u_timestamp; indicate when the date and time of the compilation + * __le32 reserved; * * The Linux driver can print both logs to the system log when a uCode error * occurs. */ - -/* - * Note: This structure is read from the device with IO accesses, - * and the reading already does the endian conversion. As it is - * read with u32-sized accesses, any members with a different size - * need to be ordered correctly though! - */ -struct iwl_error_event_table { - u32 valid; /* (nonzero) valid, (0) log is empty */ - u32 error_id; /* type of error */ - u32 pc; /* program counter */ - u32 blink1; /* branch link */ - u32 blink2; /* branch link */ - u32 ilink1; /* interrupt link */ - u32 ilink2; /* interrupt link */ - u32 data1; /* error-specific data */ - u32 data2; /* error-specific data */ - u32 line; /* source code line of error */ - u32 bcon_time; /* beacon timer */ - u32 tsf_low; /* network timestamp function timer */ - u32 tsf_hi; /* network timestamp function timer */ - u32 gp1; /* GP1 timer register */ - u32 gp2; /* GP2 timer register */ - u32 gp3; /* GP3 timer register */ - u32 ucode_ver; /* uCode version */ - u32 hw_ver; /* HW Silicon version */ - u32 brd_ver; /* HW board version */ - u32 log_pc; /* log program counter */ - u32 frame_ptr; /* frame pointer */ - u32 stack_ptr; /* stack pointer */ - u32 hcmd; /* last host command header */ -#if 0 - /* no need to read the remainder, we don't use the values */ - u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */ - u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */ - u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */ - u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */ - u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */ - u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ - u32 wait_event; /* wait event() caller address */ - u32 l2p_control; /* L2pControlField */ - u32 l2p_duration; /* L2pDurationField */ - u32 l2p_mhvalid; /* L2pMhValidBits */ - u32 l2p_addr_match; /* L2pAddrMatchStat */ - u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */ - u32 u_timestamp; /* indicate when the date and time of the compilation */ - u32 flow_handler; /* FH read/write pointers, RX credit */ -#endif -} __packed; - struct iwl_alive_resp { u8 ucode_minor; u8 ucode_major; @@ -634,6 +722,46 @@ enum { * regardless of whether RXON_FILTER_ASSOC_MSK is set. */ +struct iwl3945_rxon_cmd { + u8 node_addr[6]; + __le16 reserved1; + u8 bssid_addr[6]; + __le16 reserved2; + u8 wlap_bssid_addr[6]; + __le16 reserved3; + u8 dev_type; + u8 air_propagation; + __le16 reserved4; + u8 ofdm_basic_rates; + u8 cck_basic_rates; + __le16 assoc_id; + __le32 flags; + __le32 filter_flags; + __le16 channel; + __le16 reserved5; +} __packed; + +struct iwl4965_rxon_cmd { + u8 node_addr[6]; + __le16 reserved1; + u8 bssid_addr[6]; + __le16 reserved2; + u8 wlap_bssid_addr[6]; + __le16 reserved3; + u8 dev_type; + u8 air_propagation; + __le16 rx_chain; + u8 ofdm_basic_rates; + u8 cck_basic_rates; + __le16 assoc_id; + __le32 flags; + __le32 filter_flags; + __le16 channel; + u8 ofdm_ht_single_stream_basic_rates; + u8 ofdm_ht_dual_stream_basic_rates; +} __packed; + +/* 5000 HW just extend this command */ struct iwl_rxon_cmd { u8 node_addr[6]; __le16 reserved1; @@ -661,6 +789,25 @@ struct iwl_rxon_cmd { /* * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) */ +struct iwl3945_rxon_assoc_cmd { + __le32 flags; + __le32 filter_flags; + u8 ofdm_basic_rates; + u8 cck_basic_rates; + __le16 reserved; +} __packed; + +struct iwl4965_rxon_assoc_cmd { + __le32 flags; + __le32 filter_flags; + u8 ofdm_basic_rates; + u8 cck_basic_rates; + u8 ofdm_ht_single_stream_basic_rates; + u8 ofdm_ht_dual_stream_basic_rates; + __le16 rx_chain_select_flags; + __le16 reserved; +} __packed; + struct iwl5000_rxon_assoc_cmd { __le32 flags; __le32 filter_flags; @@ -696,6 +843,26 @@ struct iwl_rxon_time_cmd { /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ +struct iwl3945_channel_switch_cmd { + u8 band; + u8 expect_beacon; + __le16 channel; + __le32 rxon_flags; + __le32 rxon_filter_flags; + __le32 switch_time; + struct iwl3945_power_per_rate power[IWL_MAX_RATES]; +} __packed; + +struct iwl4965_channel_switch_cmd { + u8 band; + u8 expect_beacon; + __le16 channel; + __le32 rxon_flags; + __le32 rxon_filter_flags; + __le32 switch_time; + struct iwl4965_tx_power_db tx_power; +} __packed; + /** * struct iwl5000_channel_switch_cmd * @band: 0- 5.2GHz, 1- 2.4GHz @@ -809,10 +976,15 @@ struct iwl_qosparam_cmd { #define IWL_AP_ID 0 #define IWL_AP_ID_PAN 1 #define IWL_STA_ID 2 +#define IWL3945_BROADCAST_ID 24 +#define IWL3945_STATION_COUNT 25 +#define IWL4965_BROADCAST_ID 31 +#define IWL4965_STATION_COUNT 32 #define IWLAGN_PAN_BCAST_ID 14 #define IWLAGN_BROADCAST_ID 15 #define IWLAGN_STATION_COUNT 16 +#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ #define IWL_INVALID_STATION 255 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) @@ -860,6 +1032,16 @@ struct iwl_qosparam_cmd { * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) +struct iwl4965_keyinfo { + __le16 key_flags; + u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ + u8 reserved1; + __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ + u8 key_offset; + u8 reserved2; + u8 key[16]; /* 16-byte unicast decryption key */ +} __packed; + /* agn */ struct iwl_keyinfo { __le16 key_flags; @@ -901,6 +1083,7 @@ struct sta_id_modify { * with info on security keys, aggregation parameters, and Tx rates for * initial Tx attempt and any retries (agn devices uses * REPLY_TX_LINK_QUALITY_CMD, + * 3945 uses REPLY_RATE_SCALE to set up rate tables). * * REPLY_ADD_STA sets up the table entry for one station, either creating * a new entry, or modifying a pre-existing one. @@ -920,6 +1103,72 @@ struct sta_id_modify { * entries for all STAs in network, starting with index IWL_STA_ID. */ +struct iwl3945_addsta_cmd { + u8 mode; /* 1: modify existing, 0: add new station */ + u8 reserved[3]; + struct sta_id_modify sta; + struct iwl4965_keyinfo key; + __le32 station_flags; /* STA_FLG_* */ + __le32 station_flags_msk; /* STA_FLG_* */ + + /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) + * corresponding to bit (e.g. bit 5 controls TID 5). + * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ + __le16 tid_disable_tx; + + __le16 rate_n_flags; + + /* TID for which to add block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ + u8 add_immediate_ba_tid; + + /* TID for which to remove block-ack support. + * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ + u8 remove_immediate_ba_tid; + + /* Starting Sequence Number for added block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ + __le16 add_immediate_ba_ssn; +} __packed; + +struct iwl4965_addsta_cmd { + u8 mode; /* 1: modify existing, 0: add new station */ + u8 reserved[3]; + struct sta_id_modify sta; + struct iwl4965_keyinfo key; + __le32 station_flags; /* STA_FLG_* */ + __le32 station_flags_msk; /* STA_FLG_* */ + + /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) + * corresponding to bit (e.g. bit 5 controls TID 5). + * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ + __le16 tid_disable_tx; + + __le16 reserved1; + + /* TID for which to add block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ + u8 add_immediate_ba_tid; + + /* TID for which to remove block-ack support. + * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ + u8 remove_immediate_ba_tid; + + /* Starting Sequence Number for added block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ + __le16 add_immediate_ba_ssn; + + /* + * Number of packets OK to transmit to station even though + * it is asleep -- used to synchronise PS-poll and u-APSD + * responses while ucode keeps track of STA sleep state. + */ + __le16 sleep_tx_count; + + __le16 reserved2; +} __packed; + +/* agn */ struct iwl_addsta_cmd { u8 mode; /* 1: modify existing, 0: add new station */ u8 reserved[3]; @@ -1088,6 +1337,62 @@ struct iwl_wep_cmd { #define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) +struct iwl3945_rx_frame_stats { + u8 phy_count; + u8 id; + u8 rssi; + u8 agc; + __le16 sig_avg; + __le16 noise_diff; + u8 payload[0]; +} __packed; + +struct iwl3945_rx_frame_hdr { + __le16 channel; + __le16 phy_flags; + u8 reserved1; + u8 rate; + __le16 len; + u8 payload[0]; +} __packed; + +struct iwl3945_rx_frame_end { + __le32 status; + __le64 timestamp; + __le32 beacon_timestamp; +} __packed; + +/* + * REPLY_3945_RX = 0x1b (response only, not a command) + * + * NOTE: DO NOT dereference from casts to this structure + * It is provided only for calculating minimum data set size. + * The actual offsets of the hdr and end are dynamic based on + * stats.phy_count + */ +struct iwl3945_rx_frame { + struct iwl3945_rx_frame_stats stats; + struct iwl3945_rx_frame_hdr hdr; + struct iwl3945_rx_frame_end end; +} __packed; + +#define IWL39_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) + +/* Fixed (non-configurable) rx data from phy */ + +#define IWL49_RX_RES_PHY_CNT 14 +#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4) +#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70) +#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ +#define IWL49_AGC_DB_POS (7) +struct iwl4965_rx_non_cfg_phy { + __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ + __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ + u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */ + u8 pad[0]; +} __packed; + + #define IWLAGN_RX_RES_PHY_CNT 8 #define IWLAGN_RX_RES_AGC_IDX 1 #define IWLAGN_RX_RES_RSSI_AB_IDX 2 @@ -1271,6 +1576,80 @@ struct iwl_rx_mpdu_res_start { * REPLY_TX = 0x1c (command) */ +struct iwl3945_tx_cmd { + /* + * MPDU byte count: + * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, + * + 8 byte IV for CCM or TKIP (not used for WEP) + * + Data payload + * + 8-byte MIC (not used for CCM/WEP) + * NOTE: Does not include Tx command bytes, post-MAC pad bytes, + * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i + * Range: 14-2342 bytes. + */ + __le16 len; + + /* + * MPDU or MSDU byte count for next frame. + * Used for fragmentation and bursting, but not 11n aggregation. + * Same as "len", but for next frame. Set to 0 if not applicable. + */ + __le16 next_frame_len; + + __le32 tx_flags; /* TX_CMD_FLG_* */ + + u8 rate; + + /* Index of recipient station in uCode's station table */ + u8 sta_id; + u8 tid_tspec; + u8 sec_ctl; + u8 key[16]; + union { + u8 byte[8]; + __le16 word[4]; + __le32 dw[2]; + } tkip_mic; + __le32 next_frame_info; + union { + __le32 life_time; + __le32 attempt; + } stop_time; + u8 supp_rates[2]; + u8 rts_retry_limit; /*byte 50 */ + u8 data_retry_limit; /*byte 51 */ + union { + __le16 pm_frame_timeout; + __le16 attempt_duration; + } timeout; + + /* + * Duration of EDCA burst Tx Opportunity, in 32-usec units. + * Set this if txop time is not specified by HCCA protocol (e.g. by AP). + */ + __le16 driver_txop; + + /* + * MAC header goes here, followed by 2 bytes padding if MAC header + * length is 26 or 30 bytes, followed by payload data + */ + u8 payload[0]; + struct ieee80211_hdr hdr[0]; +} __packed; + +/* + * REPLY_TX = 0x1c (response) + */ +struct iwl3945_tx_resp { + u8 failure_rts; + u8 failure_frame; + u8 bt_kill_count; + u8 rate; + __le32 wireless_media_time; + __le32 status; /* TX status */ +} __packed; + + /* * 4965 uCode updates these Tx attempt count values in host DRAM. * Used for managing Tx retries when expecting block-acks. @@ -1361,6 +1740,54 @@ struct iwl_tx_cmd { struct ieee80211_hdr hdr[0]; } __packed; +/* TX command response is sent after *3945* transmission attempts. + * + * NOTES: + * + * TX_STATUS_FAIL_NEXT_FRAG + * + * If the fragment flag in the MAC header for the frame being transmitted + * is set and there is insufficient time to transmit the next frame, the + * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. + * + * TX_STATUS_FIFO_UNDERRUN + * + * Indicates the host did not provide bytes to the FIFO fast enough while + * a TX was in progress. + * + * TX_STATUS_FAIL_MGMNT_ABORT + * + * This status is only possible if the ABORT ON MGMT RX parameter was + * set to true with the TX command. + * + * If the MSB of the status parameter is set then an abort sequence is + * required. This sequence consists of the host activating the TX Abort + * control line, and then waiting for the TX Abort command response. This + * indicates that a the device is no longer in a transmit state, and that the + * command FIFO has been cleared. The host must then deactivate the TX Abort + * control line. Receiving is still allowed in this case. + */ +enum { + TX_3945_STATUS_SUCCESS = 0x01, + TX_3945_STATUS_DIRECT_DONE = 0x02, + TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, + TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, + TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, + TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, + TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, + TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, + TX_3945_STATUS_FAIL_DEST_PS = 0x88, + TX_3945_STATUS_FAIL_ABORTED = 0x89, + TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, + TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, + TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, + TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, + TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, + TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, + TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, + TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, +}; + /* * TX command response is sent after *agn* transmission attempts. * @@ -1478,6 +1905,43 @@ struct agg_tx_status { __le16 sequence; } __packed; +struct iwl4965_tx_resp { + u8 frame_count; /* 1 no aggregation, >1 aggregation */ + u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ + u8 failure_rts; /* # failures due to unsuccessful RTS */ + u8 failure_frame; /* # failures due to no ACK (unused for agg) */ + + /* For non-agg: Rate at which frame was successful. + * For agg: Rate at which all frames were transmitted. */ + __le32 rate_n_flags; /* RATE_MCS_* */ + + /* For non-agg: RTS + CTS + frame tx attempts time + ACK. + * For agg: RTS + CTS + aggregation tx time + block-ack time. */ + __le16 wireless_media_time; /* uSecs */ + + __le16 reserved; + __le32 pa_power1; /* RF power amplifier measurement (not used) */ + __le32 pa_power2; + + /* + * For non-agg: frame status TX_STATUS_* + * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status + * fields follow this one, up to frame_count. + * Bit fields: + * 11- 0: AGG_TX_STATE_* status code + * 15-12: Retry count for 1st frame in aggregation (retries + * occur if tx failed for this frame when it was a + * member of a previous aggregation block). If rate + * scaling is used, retry count indicates the rate + * table entry used for all frames in the new agg. + * 31-16: Sequence # for this frame's Tx cmd (not SSN!) + */ + union { + __le32 status; + struct agg_tx_status agg_status[0]; /* for each agg frame */ + } u; +} __packed; + /* * definitions for initial rate index field * bits [3:0] initial rate index @@ -1566,7 +2030,51 @@ struct iwl_compressed_ba_resp { /* * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) * + * See details under "TXPOWER" in iwl-4965-hw.h. + */ + +struct iwl3945_txpowertable_cmd { + u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ + u8 reserved; + __le16 channel; + struct iwl3945_power_per_rate power[IWL_MAX_RATES]; +} __packed; + +struct iwl4965_txpowertable_cmd { + u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ + u8 reserved; + __le16 channel; + struct iwl4965_tx_power_db tx_power; +} __packed; + + +/** + * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response + * + * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) + * + * NOTE: The table of rates passed to the uCode via the + * RATE_SCALE command sets up the corresponding order of + * rates used for all related commands, including rate + * masks, etc. + * + * For example, if you set 9MB (PLCP 0x0f) as the first + * rate in the rate table, the bit mask for that rate + * when passed through ofdm_basic_rates on the REPLY_RXON + * command would be bit 0 (1 << 0) */ +struct iwl3945_rate_scaling_info { + __le16 rate_n_flags; + u8 try_cnt; + u8 next_rate_index; +} __packed; + +struct iwl3945_rate_scaling_cmd { + u8 table_id; + u8 reserved[3]; + struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; +} __packed; + /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ #define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1 << 0) @@ -1622,7 +2130,7 @@ struct iwl_link_qual_general_params { #define LINK_QUAL_AGG_DISABLE_START_MAX (255) #define LINK_QUAL_AGG_DISABLE_START_MIN (0) -#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63) +#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (31) #define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) #define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0) @@ -2188,6 +2696,14 @@ struct iwl_spectrum_notification { #define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8)) #define IWL_POWER_ADVANCE_PM_ENA_MSK cpu_to_le16(BIT(9)) +struct iwl3945_powertable_cmd { + __le16 flags; + u8 reserved[2]; + __le32 rx_data_timeout; + __le32 tx_data_timeout; + __le32 sleep_interval[IWL_POWER_VEC_SIZE]; +} __packed; + struct iwl_powertable_cmd { __le16 flags; u8 keep_alive_seconds; /* 3945 reserved */ @@ -2290,6 +2806,25 @@ struct iwl_ct_kill_throttling_config { * active_dwell < max_out_time */ +/* FIXME: rename to AP1, remove tpc */ +struct iwl3945_scan_channel { + /* + * type is defined as: + * 0:0 1 = active, 0 = passive + * 1:4 SSID direct bit map; if a bit is set, then corresponding + * SSID IE is transmitted in probe request. + * 5:7 reserved + */ + u8 type; + u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */ + struct iwl3945_tx_power tpc; + __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ + __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ +} __packed; + +/* set number of direct probes u8 type */ +#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1)))) + struct iwl_scan_channel { /* * type is defined as: @@ -2385,6 +2920,50 @@ struct iwl_ssid_ie { * struct iwl_scan_channel. */ +struct iwl3945_scan_cmd { + __le16 len; + u8 reserved0; + u8 channel_count; /* # channels in channel list */ + __le16 quiet_time; /* dwell only this # millisecs on quiet channel + * (only for active scan) */ + __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ + __le16 good_CRC_th; /* passive -> active promotion threshold */ + __le16 reserved1; + __le32 max_out_time; /* max usec to be away from associated (service) + * channel */ + __le32 suspend_time; /* pause scan this long (in "extended beacon + * format") when returning to service channel: + * 3945; 31:24 # beacons, 19:0 additional usec, + * 4965; 31:22 # beacons, 21:0 additional usec. + */ + __le32 flags; /* RXON_FLG_* */ + __le32 filter_flags; /* RXON_FILTER_* */ + + /* For active scans (set to all-0s for passive scans). + * Does not include payload. Must specify Tx rate; no rate scaling. */ + struct iwl3945_tx_cmd tx_cmd; + + /* For directed active scans (set to all-0s otherwise) */ + struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945]; + + /* + * Probe request frame, followed by channel list. + * + * Size of probe request frame is specified by byte count in tx_cmd. + * Channel list follows immediately after probe request frame. + * Number of channels in list is specified by channel_count. + * Each channel in list is of type: + * + * struct iwl3945_scan_channel channels[0]; + * + * NOTE: Only one band of channels can be scanned per pass. You + * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait + * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) + * before requesting another scan. + */ + u8 data[0]; +} __packed; + enum iwl_scan_flags { /* BIT(0) currently unused */ IWL_SCAN_FLAGS_ACTION_FRAME_TX = BIT(1), @@ -2511,6 +3090,20 @@ enum iwl_ibss_manager { * BEACON_NOTIFICATION = 0x90 (notification only, not a command) */ +struct iwl3945_beacon_notif { + struct iwl3945_tx_resp beacon_notify_hdr; + __le32 low_tsf; + __le32 high_tsf; + __le32 ibss_mgr_status; +} __packed; + +struct iwl4965_beacon_notif { + struct iwl4965_tx_resp beacon_notify_hdr; + __le32 low_tsf; + __le32 high_tsf; + __le32 ibss_mgr_status; +} __packed; + struct iwlagn_beacon_notif { struct iwlagn_tx_resp beacon_notify_hdr; __le32 low_tsf; @@ -2522,6 +3115,14 @@ struct iwlagn_beacon_notif { * REPLY_TX_BEACON = 0x91 (command, has simple generic response) */ +struct iwl3945_tx_beacon_cmd { + struct iwl3945_tx_cmd tx; + __le16 tim_idx; + u8 tim_size; + u8 reserved1; + struct ieee80211_hdr frame[0]; /* beacon frame */ +} __packed; + struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; __le16 tim_idx; @@ -2558,6 +3159,53 @@ struct rate_histogram { /* statistics command response */ +struct iwl39_statistics_rx_phy { + __le32 ina_cnt; + __le32 fina_cnt; + __le32 plcp_err; + __le32 crc32_err; + __le32 overrun_err; + __le32 early_overrun_err; + __le32 crc32_good; + __le32 false_alarm_cnt; + __le32 fina_sync_err_cnt; + __le32 sfd_timeout; + __le32 fina_timeout; + __le32 unresponded_rts; + __le32 rxe_frame_limit_overrun; + __le32 sent_ack_cnt; + __le32 sent_cts_cnt; +} __packed; + +struct iwl39_statistics_rx_non_phy { + __le32 bogus_cts; /* CTS received when not expecting CTS */ + __le32 bogus_ack; /* ACK received when not expecting ACK */ + __le32 non_bssid_frames; /* number of frames with BSSID that + * doesn't belong to the STA BSSID */ + __le32 filtered_frames; /* count frames that were dumped in the + * filtering process */ + __le32 non_channel_beacons; /* beacons with our bss id but not on + * our serving channel */ +} __packed; + +struct iwl39_statistics_rx { + struct iwl39_statistics_rx_phy ofdm; + struct iwl39_statistics_rx_phy cck; + struct iwl39_statistics_rx_non_phy general; +} __packed; + +struct iwl39_statistics_tx { + __le32 preamble_cnt; + __le32 rx_detected_cnt; + __le32 bt_prio_defer_cnt; + __le32 bt_prio_kill_cnt; + __le32 few_bytes_cnt; + __le32 cts_timeout; + __le32 ack_timeout; + __le32 expected_ack_cnt; + __le32 actual_ack_cnt; +} __packed; + struct statistics_dbg { __le32 burst_check; __le32 burst_count; @@ -2565,6 +3213,23 @@ struct statistics_dbg { __le32 reserved[3]; } __packed; +struct iwl39_statistics_div { + __le32 tx_on_a; + __le32 tx_on_b; + __le32 exec_time; + __le32 probe_time; +} __packed; + +struct iwl39_statistics_general { + __le32 temperature; + struct statistics_dbg dbg; + __le32 sleep_time; + __le32 slots_out; + __le32 slots_idle; + __le32 ttl_timestamp; + struct iwl39_statistics_div div; +} __packed; + struct statistics_rx_phy { __le32 ina_cnt; __le32 fina_cnt; @@ -2806,6 +3471,13 @@ struct iwl_statistics_cmd { #define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) #define STATISTICS_REPLY_FLG_HT40_MODE_MSK cpu_to_le32(0x8) +struct iwl3945_notif_statistics { + __le32 flag; + struct iwl39_statistics_rx rx; + struct iwl39_statistics_tx tx; + struct iwl39_statistics_general general; +} __packed; + struct iwl_notif_statistics { __le32 flag; struct statistics_rx rx; @@ -3779,6 +4451,10 @@ struct iwl_rx_packet { __le32 len_n_flags; struct iwl_cmd_header hdr; union { + struct iwl3945_rx_frame rx_frame; + struct iwl3945_tx_resp tx_resp; + struct iwl3945_beacon_notif beacon_status; + struct iwl_alive_resp alive_frame; struct iwl_spectrum_notification spectrum_notif; struct iwl_csa_notification csa_notif; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 46d69657407c..6c30fa652e27 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -67,6 +67,30 @@ u32 iwl_debug_level; const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + +/* This function both allocates and initializes hw and priv. */ +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) +{ + struct iwl_priv *priv; + /* mac80211 allocates memory for this device instance, including + * space for this driver's private structure */ + struct ieee80211_hw *hw; + + hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), + cfg->ops->ieee80211_ops); + if (hw == NULL) { + pr_err("%s: Can not allocate network device\n", + cfg->name); + goto out; + } + + priv = hw->priv; + priv->hw = hw; + +out: + return hw; +} + #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, @@ -866,21 +890,10 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); } #endif - -static void iwlagn_abort_notification_waits(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl_notification_wait *wait_entry; - - spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags); - list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list) - wait_entry->aborted = true; - spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags); - - wake_up_all(&priv->_agn.notif_waitq); -} - -void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card + */ +void iwl_irq_handle_error(struct iwl_priv *priv) { unsigned int reload_msec; unsigned long reload_jiffies; @@ -891,64 +904,18 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - iwlagn_abort_notification_waits(priv); - - /* Keep the restart process from trying to send host - * commands by clearing the ready bit */ - clear_bit(STATUS_READY, &priv->status); - - wake_up_interruptible(&priv->wait_command_queue); - - if (!ondemand) { - /* - * If firmware keep reloading, then it indicate something - * serious wrong and firmware having problem to recover - * from it. Instead of keep trying which will fill the syslog - * and hang the system, let's just stop it - */ - reload_jiffies = jiffies; - reload_msec = jiffies_to_msecs((long) reload_jiffies - - (long) priv->reload_jiffies); - priv->reload_jiffies = reload_jiffies; - if (reload_msec <= IWL_MIN_RELOAD_DURATION) { - priv->reload_count++; - if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { - IWL_ERR(priv, "BUG_ON, Stop restarting\n"); - return; - } - } else - priv->reload_count = 0; - } - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - if (priv->cfg->mod_params->restart_fw) { - IWL_DEBUG(priv, IWL_DL_FW_ERRORS, - "Restarting adapter due to uCode error.\n"); - queue_work(priv->workqueue, &priv->restart); - } else - IWL_DEBUG(priv, IWL_DL_FW_ERRORS, - "Detected FW error, but not restarting\n"); - } -} - -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -void iwl_irq_handle_error(struct iwl_priv *priv) -{ /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ if (priv->cfg->internal_wimax_coex && (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & APMS_CLK_VAL_MRB_FUNC_MODE) || (iwl_read_prph(priv, APMG_PS_CTRL_REG) & APMG_PS_CTRL_VAL_RESET_REQ))) { + wake_up_interruptible(&priv->wait_command_queue); /* - * Keep the restart process from trying to send host - * commands by clearing the ready bit. + *Keep the restart process from trying to send host + * commands by clearing the INIT status bit */ clear_bit(STATUS_READY, &priv->status); - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); IWL_ERR(priv, "RF is used by WiMAX\n"); return; } @@ -956,17 +923,50 @@ void iwl_irq_handle_error(struct iwl_priv *priv) IWL_ERR(priv, "Loaded firmware version: %s\n", priv->hw->wiphy->fw_version); - iwl_dump_nic_error_log(priv); - iwl_dump_csr(priv); - iwl_dump_fh(priv, NULL, false); - iwl_dump_nic_event_log(priv, false, NULL, false); + priv->cfg->ops->lib->dump_nic_error_log(priv); + if (priv->cfg->ops->lib->dump_csr) + priv->cfg->ops->lib->dump_csr(priv); + if (priv->cfg->ops->lib->dump_fh) + priv->cfg->ops->lib->dump_fh(priv, NULL, false); + priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) iwl_print_rx_config_cmd(priv, &priv->contexts[IWL_RXON_CTX_BSS]); #endif - iwlagn_fw_error(priv, false); + wake_up_interruptible(&priv->wait_command_queue); + + /* Keep the restart process from trying to send host + * commands by clearing the INIT status bit */ + clear_bit(STATUS_READY, &priv->status); + + /* + * If firmware keep reloading, then it indicate something + * serious wrong and firmware having problem to recover + * from it. Instead of keep trying which will fill the syslog + * and hang the system, let's just stop it + */ + reload_jiffies = jiffies; + reload_msec = jiffies_to_msecs((long) reload_jiffies - + (long) priv->reload_jiffies); + priv->reload_jiffies = reload_jiffies; + if (reload_msec <= IWL_MIN_RELOAD_DURATION) { + priv->reload_count++; + if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { + IWL_ERR(priv, "BUG_ON, Stop restarting\n"); + return; + } + } else + priv->reload_count = 0; + + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, + "Restarting adapter due to uCode error.\n"); + + if (priv->cfg->mod_params->restart_fw) + queue_work(priv->workqueue, &priv->restart); + } } static int iwl_apm_stop_master(struct iwl_priv *priv) @@ -1040,6 +1040,7 @@ int iwl_apm_init(struct iwl_priv *priv) /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s + * NOTE: This is no-op for 3945 (non-existant bit) */ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); @@ -1052,18 +1053,20 @@ int iwl_apm_init(struct iwl_priv *priv) * If not (unlikely), enable L0S, so there is at least some * power savings, even without L1. */ - lctl = iwl_pcie_link_ctl(priv); - if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == - PCI_CFG_LINK_CTRL_VAL_L1_EN) { - /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(priv, CSR_GIO_REG, - CSR_GIO_REG_VAL_L0S_ENABLED); - IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); - } else { - /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(priv, CSR_GIO_REG, - CSR_GIO_REG_VAL_L0S_ENABLED); - IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); + if (priv->cfg->base_params->set_l0s) { + lctl = iwl_pcie_link_ctl(priv); + if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == + PCI_CFG_LINK_CTRL_VAL_L1_EN) { + /* L1-ASPM enabled; disable(!) L0S */ + iwl_set_bit(priv, CSR_GIO_REG, + CSR_GIO_REG_VAL_L0S_ENABLED); + IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); + } else { + /* L1-ASPM disabled; enable(!) L0S */ + iwl_clear_bit(priv, CSR_GIO_REG, + CSR_GIO_REG_VAL_L0S_ENABLED); + IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); + } } /* Configure analog phase-lock-loop before activating to D0A */ @@ -1091,13 +1094,21 @@ int iwl_apm_init(struct iwl_priv *priv) } /* - * Enable DMA clock and wait for it to stabilize. + * Enable DMA and BSM (if used) clocks, wait for them to stabilize. + * BSM (Boostrap State Machine) is only in 3945 and 4965; + * later devices (i.e. 5000 and later) have non-volatile SRAM, + * and don't need BSM to restore data after power-saving sleep. * * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); + if (priv->cfg->base_params->use_bsm) + iwl_write_prph(priv, APMG_CLK_EN_REG, + APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); + else + iwl_write_prph(priv, APMG_CLK_EN_REG, + APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ @@ -1419,6 +1430,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, iwl_teardown_interface(priv, vif, false); + memset(priv->bssid, 0, ETH_ALEN); mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1744,7 +1756,15 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) break; } IWL_ERR(priv, "On demand firmware reload\n"); - iwlagn_fw_error(priv, true); + /* Set the FW error flag -- cleared on iwl_down */ + set_bit(STATUS_FW_ERROR, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); + /* + * Keep the restart process from trying to send host + * commands by clearing the INIT status bit + */ + clear_bit(STATUS_READY, &priv->status); + queue_work(priv->workqueue, &priv->restart); break; } return 0; @@ -1763,15 +1783,6 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&priv->mutex); - if (!ctx->vif || !iwl_is_ready_rf(priv)) { - /* - * Huh? But wait ... this can maybe happen when - * we're in the middle of a firmware restart! - */ - err = -EBUSY; - goto out; - } - interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; if (!(interface_modes & BIT(newtype))) { @@ -1799,7 +1810,6 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* success */ iwl_teardown_interface(priv, vif, true); vif->type = newtype; - vif->p2p = newp2p; err = iwl_setup_interface(priv, ctx); WARN_ON(err); /* diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index 32a990ff09ae..b316d833d9a2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,7 +73,7 @@ struct iwl_cmd; #define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" #define DRV_AUTHOR "" #define IWL_PCI_DEVICE(dev, subdev, cfg) \ @@ -122,6 +122,14 @@ struct iwl_apm_ops { void (*config)(struct iwl_priv *priv); }; +struct iwl_isr_ops { + irqreturn_t (*isr) (int irq, void *data); + void (*free)(struct iwl_priv *priv); + int (*alloc)(struct iwl_priv *priv); + int (*reset)(struct iwl_priv *priv); + void (*disable)(struct iwl_priv *priv); +}; + struct iwl_debugfs_ops { ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); @@ -139,6 +147,12 @@ struct iwl_temp_ops { void (*temperature)(struct iwl_priv *priv); }; +struct iwl_tt_ops { + bool (*lower_power_detection)(struct iwl_priv *priv); + u8 (*tt_power_mode)(struct iwl_priv *priv); + bool (*ct_kill_check)(struct iwl_priv *priv); +}; + struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -157,14 +171,30 @@ struct iwl_lib_ops { struct iwl_tx_queue *txq); int (*txq_init)(struct iwl_priv *priv, struct iwl_tx_queue *txq); + /* aggregations */ + int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, + int sta_id, int tid, u16 ssn_idx); + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, + u8 tx_fifo); /* setup Rx handler */ void (*rx_handler_setup)(struct iwl_priv *priv); /* setup deferred work */ void (*setup_deferred_work)(struct iwl_priv *priv); /* cancel deferred work */ void (*cancel_deferred_work)(struct iwl_priv *priv); + /* alive notification after init uCode load */ + void (*init_alive_start)(struct iwl_priv *priv); + /* alive notification */ + int (*alive_notify)(struct iwl_priv *priv); /* check validity of rtc data address */ int (*is_valid_rtc_data_addr)(u32 addr); + /* 1st ucode load */ + int (*load_ucode)(struct iwl_priv *priv); + int (*dump_nic_event_log)(struct iwl_priv *priv, + bool full_log, char **buf, bool display); + void (*dump_nic_error_log)(struct iwl_priv *priv); + void (*dump_csr)(struct iwl_priv *priv); + int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); int (*set_channel_switch)(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch); /* power management */ @@ -174,6 +204,9 @@ struct iwl_lib_ops { int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); + /* isr */ + struct iwl_isr_ops isr_ops; + /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; @@ -184,6 +217,13 @@ struct iwl_lib_ops { void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); struct iwl_debugfs_ops debugfs_ops; + + /* thermal throttling */ + struct iwl_tt_ops tt_ops; +}; + +struct iwl_led_ops { + int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); }; /* NIC specific ops */ @@ -191,15 +231,28 @@ struct iwl_nic_ops { void (*additional_nic_config)(struct iwl_priv *priv); }; +struct iwl_legacy_ops { + void (*post_associate)(struct iwl_priv *priv); + void (*config_ap)(struct iwl_priv *priv); + /* station management */ + int (*update_bcast_stations)(struct iwl_priv *priv); + int (*manage_ibss_station)(struct iwl_priv *priv, + struct ieee80211_vif *vif, bool add); +}; + struct iwl_ops { const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; + const struct iwl_led_ops *led; const struct iwl_nic_ops *nic; + const struct iwl_legacy_ops *legacy; + const struct ieee80211_ops *ieee80211_ops; }; struct iwl_mod_params { int sw_crypto; /* def: 0 = using hardware encryption */ + int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ int disable_11n; /* def: 0 = 11n capabilities enabled */ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ @@ -225,7 +278,16 @@ struct iwl_mod_params { * @wd_timeout: TX queues watchdog timeout * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging + * @tx_power_by_driver: tx power calibration performed by driver + * instead of uCode + * @ucode_tracing: support ucode continuous tracing + * @sensitivity_calib_by_driver: driver has the capability to perform + * sensitivity calibration operation + * @chain_noise_calib_by_driver: driver has the capability to perform + * chain noise calibration operation * @shadow_reg_enable: HW shadhow register bit + * @no_agg_framecnt_info: uCode do not provide aggregation frame count + * information */ struct iwl_base_params { int eeprom_size; @@ -233,10 +295,14 @@ struct iwl_base_params { int num_of_ampdu_queues;/* def: HW dependent */ /* for iwl_apm_init() */ u32 pll_cfg_val; + bool set_l0s; + bool use_bsm; + bool use_isr_legacy; const u16 max_ll_items; const bool shadow_ram_support; u16 led_compensation; + const bool broken_powersave; int chain_noise_num_beacons; bool adv_thermal_throttle; bool support_ct_kill_exit; @@ -246,12 +312,18 @@ struct iwl_base_params { unsigned int wd_timeout; bool temperature_kelvin; u32 max_event_log_size; + const bool tx_power_by_driver; + const bool ucode_tracing; + const bool sensitivity_calib_by_driver; + const bool chain_noise_calib_by_driver; const bool shadow_reg_enable; + const bool no_agg_framecnt_info; }; /* * @advanced_bt_coexist: support advanced bt coexist * @bt_init_traffic_load: specify initial bt traffic load * @bt_prio_boost: default bt priority boost value + * @bt_statistics: use BT version of statistics notification * @agg_time_limit: maximum number of uSec in aggregation * @ampdu_factor: Maximum A-MPDU length factor * @ampdu_density: Minimum A-MPDU spacing @@ -261,6 +333,7 @@ struct iwl_bt_params { bool advanced_bt_coexist; u8 bt_init_traffic_load; u8 bt_prio_boost; + const bool bt_statistics; u16 agg_time_limit; u8 ampdu_factor; u8 ampdu_density; @@ -291,7 +364,6 @@ struct iwl_ht_params { * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device * @iq_invert: I/Q inversion - * @disable_otp_refresh: disable OTP refresh current limit * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -342,13 +414,13 @@ struct iwl_cfg { const bool rx_with_siso_diversity; const bool internal_wimax_coex; const bool iq_invert; - const bool disable_otp_refresh; }; /*************************** * L i b * ***************************/ +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); @@ -553,8 +625,6 @@ extern const struct dev_pm_ops iwl_pm_ops; void iwl_dump_nic_error_log(struct iwl_priv *priv); int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); -void iwl_dump_csr(struct iwl_priv *priv); -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -666,10 +736,12 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) priv->cfg->bt_params->advanced_bt_coexist; } +static inline bool iwl_bt_statistics(struct iwl_priv *priv) +{ + return priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics; +} + extern bool bt_coex_active; extern bool bt_siso_mode; - -void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); - #endif /* __iwl_core_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h b/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h index 5ab90ba7a024..f52bc040bcbf 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -155,10 +155,18 @@ #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) /* Bits for CSR_HW_IF_CONFIG_REG */ +#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) +#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100) +#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200) +#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) +#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) +#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) +#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) + #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ @@ -178,7 +186,7 @@ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ -#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */ +#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ #define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ #define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ @@ -194,17 +202,29 @@ /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ #define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ +#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ #define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ #define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ +#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ #define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ #define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ -#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) +#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ + CSR39_FH_INT_BIT_RX_CHNL2 | \ + CSR_FH_INT_BIT_RX_CHNL1 | \ + CSR_FH_INT_BIT_RX_CHNL0) + + +#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \ + CSR_FH_INT_BIT_TX_CHNL1 | \ + CSR_FH_INT_BIT_TX_CHNL0) + +#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ + CSR_FH_INT_BIT_RX_CHNL1 | \ + CSR_FH_INT_BIT_RX_CHNL0) -#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) +#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ + CSR_FH_INT_BIT_TX_CHNL0) /* GPIO */ #define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) @@ -248,7 +268,7 @@ * Indicates MAC (ucode processor, etc.) is powered up and can run. * Internal resources are accessible. * NOTE: This does not indicate that the processor is actually running. - * NOTE: This does not indicate that device has completed + * NOTE: This does not indicate that 4965 or 3945 has completed * init or post-power-down restore of internal SRAM memory. * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that * SRAM is restored and uCode is in normal operation mode. @@ -271,6 +291,8 @@ /* HW REV */ #define CSR_HW_REV_TYPE_MSK (0x00001F0) +#define CSR_HW_REV_TYPE_3945 (0x00000D0) +#define CSR_HW_REV_TYPE_4965 (0x0000000) #define CSR_HW_REV_TYPE_5300 (0x0000020) #define CSR_HW_REV_TYPE_5350 (0x0000030) #define CSR_HW_REV_TYPE_5100 (0x0000050) @@ -341,7 +363,7 @@ * 0: MAC_SLEEP * uCode sets this when preparing a power-saving power-down. * uCode resets this when power-up is complete and SRAM is sane. - * NOTE: device saves internal SRAM data to host when powering down, + * NOTE: 3945/4965 saves internal SRAM data to host when powering down, * and must restore this data after powering back up. * MAC_SLEEP is the best indication that restore is complete. * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and @@ -372,6 +394,7 @@ #define CSR_LED_REG_TRUN_OFF (0x38) /* ANA_PLL */ +#define CSR39_ANA_PLL_CFG_VAL (0x01000000) #define CSR50_ANA_PLL_CFG_VAL (0x00880300) /* HPET MEM debug */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h index 2824ccbcc1fc..ebdea3be3ef9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * @@ -146,6 +146,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_RX (1 << 24) #define IWL_DL_ISR (1 << 25) #define IWL_DL_HT (1 << 26) +#define IWL_DL_IO (1 << 27) /* 0xF0000000 - 0x10000000 */ #define IWL_DL_11H (1 << 28) #define IWL_DL_STATS (1 << 29) @@ -173,6 +174,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a) #define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a) +#define IWL_DEBUG_IO(p, f, a...) IWL_DEBUG(p, IWL_DL_IO, f, ## a) #define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a) #define IWL_DEBUG_RATE_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7bd4f5af5b0d..8842411f1cf3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -226,10 +226,10 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { priv->dbgfs_sram_offset = 0x800000; - if (priv->ucode_type == UCODE_SUBTYPE_INIT) - priv->dbgfs_sram_len = priv->ucode_init.data.len; + if (priv->ucode_type == UCODE_INIT) + priv->dbgfs_sram_len = priv->ucode_init_data.len; else - priv->dbgfs_sram_len = priv->ucode_rt.data.len; + priv->dbgfs_sram_len = priv->ucode_data.len; } len = priv->dbgfs_sram_len; @@ -437,7 +437,8 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file, int pos = 0; ssize_t ret = -ENOMEM; - ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); + ret = pos = priv->cfg->ops->lib->dump_nic_event_log( + priv, true, &buf, true); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); @@ -461,7 +462,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, if (sscanf(buf, "%d", &event_log_flag) != 1) return -EFAULT; if (event_log_flag == 1) - iwl_dump_nic_event_log(priv, true, NULL, false); + priv->cfg->ops->lib->dump_nic_event_log(priv, true, + NULL, false); return count; } @@ -1266,7 +1268,8 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, if (sscanf(buf, "%d", &csr) != 1) return -EFAULT; - iwl_dump_csr(priv); + if (priv->cfg->ops->lib->dump_csr) + priv->cfg->ops->lib->dump_csr(priv); return count; } @@ -1356,11 +1359,13 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, int pos = 0; ssize_t ret = -EFAULT; - ret = pos = iwl_dump_fh(priv, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, - count, ppos, buf, pos); - kfree(buf); + if (priv->cfg->ops->lib->dump_fh) { + ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); + kfree(buf); + } } return ret; @@ -1567,10 +1572,12 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, int pos = 0; char buf[200]; const size_t bufsz = sizeof(buf); + ssize_t ret; if (!priv->bt_enable_flag) { pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; } pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", priv->bt_enable_flag); @@ -1601,7 +1608,8 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, break; } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; } static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, @@ -1723,8 +1731,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); - DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); + if (!priv->cfg->base_params->broken_powersave) { + DEBUGFS_ADD_FILE(sleep_level_override, dir_data, + S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); + } DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); @@ -1747,20 +1758,29 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); + if (priv->cfg->base_params->sensitivity_calib_by_driver) + DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); + if (priv->cfg->base_params->chain_noise_calib_by_driver) + DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); + if (priv->cfg->base_params->ucode_tracing) + DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); + if (iwl_bt_statistics(priv)) + DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); if (iwl_advanced_bt_coexist(priv)) DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); - DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, - &priv->disable_sens_cal); - DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, - &priv->disable_chain_noise_cal); + if (priv->cfg->base_params->sensitivity_calib_by_driver) + DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, + &priv->disable_sens_cal); + if (priv->cfg->base_params->chain_noise_calib_by_driver) + DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, + &priv->disable_chain_noise_cal); + if (priv->cfg->base_params->tx_power_by_driver) + DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, + &priv->disable_tx_power_cal); return 0; err: diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index 197fa742f79a..68b953f2bdc7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -26,6 +26,7 @@ /* * Please use this file (iwl-dev.h) for driver implementation definitions. * Please use iwl-commands.h for uCode API definitions. + * Please use iwl-4965-hw.h for hardware-related definitions. */ #ifndef __iwl_dev_h__ @@ -178,12 +179,53 @@ struct iwl_tx_queue { #define IWL_NUM_SCAN_RATES (2) +struct iwl4965_channel_tgd_info { + u8 type; + s8 max_power; +}; + +struct iwl4965_channel_tgh_info { + s64 last_radar_time; +}; + +#define IWL4965_MAX_RATE (33) + +struct iwl3945_clip_group { + /* maximum power level to prevent clipping for each rate, derived by + * us from this band's saturation power in EEPROM */ + const s8 clip_powers[IWL_MAX_RATES]; +}; + +/* current Tx power values to use, one for each rate for each channel. + * requested power is limited by: + * -- regulatory EEPROM limits for this channel + * -- hardware capabilities (clip-powers) + * -- spectrum management + * -- user preference (e.g. iwconfig) + * when requested power is set, base power index must also be set. */ +struct iwl3945_channel_power_info { + struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ + s8 power_table_index; /* actual (compenst'd) index into gain table */ + s8 base_power_index; /* gain index for power at factory temp. */ + s8 requested_power; /* power (dBm) requested for this chnl/rate */ +}; + +/* current scan Tx power values to use, one for each scan rate for each + * channel. */ +struct iwl3945_scan_power_info { + struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ + s8 power_table_index; /* actual (compenst'd) index into gain table */ + s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ +}; + /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant * with one another! */ struct iwl_channel_info { + struct iwl4965_channel_tgd_info tgd; + struct iwl4965_channel_tgh_info tgh; struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for * HT40 channel */ @@ -203,6 +245,14 @@ struct iwl_channel_info { s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ u8 ht40_flags; /* flags copied from EEPROM */ u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ + + /* Radio/DSP gain settings for each "normal" data Tx rate. + * These include, in addition to RF and DSP gain, a few fields for + * remembering/modifying gain settings (indexes). */ + struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE]; + + /* Radio/DSP gain settings for each scan rate, for directed scans. */ + struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; #define IWL_TX_FIFO_BK 0 /* shared */ @@ -259,7 +309,6 @@ enum { CMD_SIZE_HUGE = (1 << 0), CMD_ASYNC = (1 << 1), CMD_WANT_SKB = (1 << 2), - CMD_MAPPED = (1 << 3), }; #define DEF_CMD_PAYLOAD_SIZE 320 @@ -367,7 +416,6 @@ struct iwl_ht_agg { #define IWL_EMPTYING_HW_QUEUE_ADDBA 2 #define IWL_EMPTYING_HW_QUEUE_DELBA 3 u8 state; - u8 tx_fifo; }; @@ -451,6 +499,9 @@ struct iwl_station_priv_common { * When mac80211 creates a station it reserves some space (hw->sta_data_size) * in the structure for use by driver. This structure is places in that * space. + * + * The common struct MUST be first because it is shared between + * 3945 and agn! */ struct iwl_station_priv { struct iwl_station_priv_common common; @@ -479,10 +530,6 @@ struct fw_desc { u32 len; /* bytes */ }; -struct fw_img { - struct fw_desc code, data; -}; - /* v1/v2 uCode file layout */ struct iwl_ucode_header { __le32 ver; /* major/minor/API/serial */ @@ -539,21 +586,6 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, - /* 16 and 17 reserved for future use */ - IWL_UCODE_TLV_FLAGS = 18, -}; - -/** - * enum iwl_ucode_tlv_flag - ucode API flags - * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously - * was a separate TLV but moved here to save space. - * @IWL_UCODE_TLV_FLAGS_RESERVED_1: reserved - * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). - */ -enum iwl_ucode_tlv_flag { - IWL_UCODE_TLV_FLAGS_PAN = BIT(0), - IWL_UCODE_TLV_FLAGS_RESERVED_1 = BIT(1), - IWL_UCODE_TLV_FLAGS_MFP = BIT(2), }; struct iwl_ucode_tlv { @@ -587,6 +619,14 @@ struct iwl_tlv_ucode_header { u8 data[0]; }; +struct iwl4965_ibss_seq { + u8 mac[ETH_ALEN]; + u16 seq_num; + u16 frag_num; + unsigned long packet_time; + struct list_head list; +}; + struct iwl_sensitivity_ranges { u16 min_nrg_cck; u16 max_nrg_cck; @@ -660,6 +700,7 @@ struct iwl_hw_params { u8 max_beacon_itrvl; /* in 1024 ms */ u32 max_inst_size; u32 max_data_size; + u32 max_bsm_size; u32 ct_kill_threshold; /* value in hw-dependent units */ u32 ct_kill_exit_threshold; /* value in hw-dependent units */ /* for 1000, 6000 series and up */ @@ -681,6 +722,8 @@ struct iwl_hw_params { * Naming convention -- * iwl_ <-- Is part of iwlwifi * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) + * iwl4965_bg_ <-- Called from work queue context + * iwl4965_mac_ <-- mac80211 callback * ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); @@ -729,6 +772,7 @@ struct iwl_dma_ptr { /* Sensitivity and chain noise calibration */ #define INITIALIZATION_VALUE 0xFFFF +#define IWL4965_CAL_NUM_BEACONS 20 #define IWL_CAL_NUM_BEACONS 16 #define MAXIMUM_ALLOWED_PATHLOSS 15 @@ -762,19 +806,24 @@ struct iwl_dma_ptr { #define NRG_NUM_PREV_STAT_L 20 #define NUM_RX_CHAINS 3 -enum iwlagn_false_alarm_state { +enum iwl4965_false_alarm_state { IWL_FA_TOO_MANY = 0, IWL_FA_TOO_FEW = 1, IWL_FA_GOOD_RANGE = 2, }; -enum iwlagn_chain_noise_state { +enum iwl4965_chain_noise_state { IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */ IWL_CHAIN_NOISE_ACCUMULATE, IWL_CHAIN_NOISE_CALIBRATED, IWL_CHAIN_NOISE_DONE, }; +enum iwl4965_calib_enabled_state { + IWL_CALIB_DISABLED = 0, /* must be 0 */ + IWL_CALIB_ENABLED = 1, +}; + /* * enum iwl_calib @@ -798,6 +847,12 @@ struct iwl_calib_result { size_t buf_len; }; +enum ucode_type { + UCODE_NONE = 0, + UCODE_INIT, + UCODE_RT +}; + /* Sensitivity calib data */ struct iwl_sensitivity_data { u32 auto_corr_ofdm; @@ -1075,6 +1130,12 @@ struct iwl_force_reset { }; /* extend beacon time format bit shifting */ +/* + * for _3945 devices + * bits 31:24 - extended + * bits 23:0 - interval + */ +#define IWL3945_EXT_BEACON_TIME_POS 24 /* * for _agn devices * bits 31:22 - extended @@ -1103,12 +1164,10 @@ struct iwl_force_reset { struct iwl_notification_wait { struct list_head list; - void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, - void *data); - void *fn_data; + void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); u8 cmd; - bool triggered, aborted; + bool triggered; }; enum iwl_rxon_context_id { @@ -1169,8 +1228,6 @@ struct iwl_rxon_context { bool enabled, is_40mhz; u8 extension_chan_offset; } ht; - - bool last_tx_rejected; }; enum iwl_scan_type { @@ -1192,6 +1249,7 @@ struct iwl_priv { int frames_count; enum ieee80211_band band; + int alloc_rxb_page; void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); @@ -1247,12 +1305,16 @@ struct iwl_priv { spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; + struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ /* basic pci-network driver stuff */ struct pci_dev *pci_dev; /* pci hardware address support */ void __iomem *hw_base; + u32 hw_rev; + u32 hw_wa_rev; + u8 rev_id; /* microcode/device supports multiple contexts */ u8 valid_contexts; @@ -1270,10 +1332,13 @@ struct iwl_priv { int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ - struct fw_img ucode_rt; - struct fw_img ucode_init; - - enum iwlagn_ucode_subtype ucode_type; + struct fw_desc ucode_code; /* runtime inst */ + struct fw_desc ucode_data; /* runtime data original */ + struct fw_desc ucode_data_backup; /* runtime data save/restore */ + struct fw_desc ucode_init; /* initialization inst */ + struct fw_desc ucode_init_data; /* initialization data */ + struct fw_desc ucode_boot; /* bootstrap inst */ + enum ucode_type ucode_type; u8 ucode_write_complete; /* the image write is complete */ char firmware_name[25]; @@ -1281,10 +1346,10 @@ struct iwl_priv { struct iwl_switch_rxon switch_rxon; - struct { - u32 error_event_table; - u32 log_event_table; - } device_pointers; + /* 1st responses from initialize and runtime uCode images. + * _agn's initialize alive response contains some calibration data. */ + struct iwl_init_alive_resp card_alive_init; + struct iwl_alive_resp card_alive; u16 active_rate; @@ -1325,12 +1390,15 @@ struct iwl_priv { struct iwl_power_mgr power_data; struct iwl_tt_mgmt thermal_throttle; + /* context information */ + u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ + /* station table variables */ /* Note: if lock and sta_lock are needed, lock must be acquired first */ spinlock_t sta_lock; int num_stations; - struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; + struct iwl_station_entry stations[IWL_STATION_COUNT]; unsigned long ucode_key_table; /* queue refcounts */ @@ -1354,81 +1422,101 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; - struct { - __le32 flag; - struct statistics_general_common common; - struct statistics_rx_non_phy rx_non_phy; - struct statistics_rx_phy rx_ofdm; - struct statistics_rx_ht_phy rx_ofdm_ht; - struct statistics_rx_phy rx_cck; - struct statistics_tx tx; + union { +#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) + struct { + void *shared_virt; + dma_addr_t shared_phys; + + struct delayed_work thermal_periodic; + struct delayed_work rfkill_poll; + + struct iwl3945_notif_statistics statistics; #ifdef CONFIG_IWLWIFI_DEBUGFS - struct statistics_bt_activity bt_activity; - __le32 num_bt_kills, accum_num_bt_kills; + struct iwl3945_notif_statistics accum_statistics; + struct iwl3945_notif_statistics delta_statistics; + struct iwl3945_notif_statistics max_delta; +#endif + + u32 sta_supp_rates; + int last_rx_rssi; /* From Rx packet statistics */ + + /* Rx'd packet timing information */ + u32 last_beacon_time; + u64 last_tsf; + + /* + * each calibration channel group in the + * EEPROM has a derived clip setting for + * each rate. + */ + const struct iwl3945_clip_group clip_groups[5]; + + } _3945; #endif - } statistics; +#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) + struct { + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; + /* + * reporting the number of tids has AGG on. 0 means + * no AGGREGATION + */ + u8 agg_tids_count; + + struct iwl_rx_phy_res last_phy_res; + bool last_phy_res_valid; + + struct completion firmware_loading_complete; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; + + /* + * chain noise reset and gain commands are the + * two extra calibration commands follows the standard + * phy calibration commands + */ + u8 phy_calib_chain_noise_reset_cmd; + u8 phy_calib_chain_noise_gain_cmd; + + struct iwl_notif_statistics statistics; + struct iwl_bt_notif_statistics statistics_bt; + /* counts reply_tx error */ + struct reply_tx_error_statistics reply_tx_stats; + struct reply_agg_tx_error_statistics reply_agg_tx_stats; #ifdef CONFIG_IWLWIFI_DEBUGFS - struct { - struct statistics_general_common common; - struct statistics_rx_non_phy rx_non_phy; - struct statistics_rx_phy rx_ofdm; - struct statistics_rx_ht_phy rx_ofdm_ht; - struct statistics_rx_phy rx_cck; - struct statistics_tx tx; - struct statistics_bt_activity bt_activity; - } accum_stats, delta_stats, max_delta_stats; + struct iwl_notif_statistics accum_statistics; + struct iwl_notif_statistics delta_statistics; + struct iwl_notif_statistics max_delta; + struct iwl_bt_notif_statistics accum_statistics_bt; + struct iwl_bt_notif_statistics delta_statistics_bt; + struct iwl_bt_notif_statistics max_delta_bt; #endif - struct { - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; - /* - * reporting the number of tids has AGG on. 0 means - * no AGGREGATION - */ - u8 agg_tids_count; - - struct iwl_rx_phy_res last_phy_res; - bool last_phy_res_valid; - - struct completion firmware_loading_complete; - - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; - - /* - * chain noise reset and gain commands are the - * two extra calibration commands follows the standard - * phy calibration commands - */ - u8 phy_calib_chain_noise_reset_cmd; - u8 phy_calib_chain_noise_gain_cmd; - - /* counts reply_tx error */ - struct reply_tx_error_statistics reply_tx_stats; - struct reply_agg_tx_error_statistics reply_agg_tx_stats; - /* notification wait support */ - struct list_head notif_waits; - spinlock_t notif_wait_lock; - wait_queue_head_t notif_waitq; - - /* remain-on-channel offload support */ - struct ieee80211_channel *hw_roc_channel; - struct delayed_work hw_roc_work; - enum nl80211_channel_type hw_roc_chantype; - int hw_roc_duration; - bool hw_roc_setup; - - struct sk_buff *offchan_tx_skb; - int offchan_tx_timeout; - struct ieee80211_channel *offchan_tx_chan; - } _agn; + /* notification wait support */ + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; + + /* remain-on-channel offload support */ + struct ieee80211_channel *hw_roc_channel; + struct delayed_work hw_roc_work; + enum nl80211_channel_type hw_roc_chantype; + int hw_roc_duration; + + struct sk_buff *offchan_tx_skb; + int offchan_tx_timeout; + struct ieee80211_channel *offchan_tx_chan; + } _agn; +#endif + }; /* bt coex */ u8 bt_enable_flag; @@ -1471,6 +1559,8 @@ struct iwl_priv { struct tasklet_struct irq_tasklet; + struct delayed_work init_alive_start; + struct delayed_work alive_start; struct delayed_work scan_check; /* TX Power */ @@ -1499,10 +1589,12 @@ struct iwl_priv { struct work_struct txpower_work; u32 disable_sens_cal; u32 disable_chain_noise_cal; + u32 disable_tx_power_cal; struct work_struct run_time_calib_work; struct timer_list statistics_periodic; struct timer_list ucode_trace; struct timer_list watchdog; + bool hw_ready; struct iwl_event_log event_log; @@ -1618,10 +1710,12 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) { __free_pages(page, priv->hw_params.rx_page_order); + priv->alloc_rxb_page--; } static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) { free_pages(page, priv->hw_params.rx_page_order); + priv->alloc_rxb_page--; } #endif /* __iwl_dev_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c index a635a7e75447..4a487639d932 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h index f00172cb8a6d..4cf864c664ee 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 402733638f50..833194a2c639 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -188,16 +188,18 @@ static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) CSR_OTP_GP_REG_OTP_ACCESS_MODE); } -static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) +static int iwlcore_get_nvm_type(struct iwl_priv *priv) { u32 otpgp; int nvm_type; /* OTP only valid for CP/PP and after */ - switch (hw_rev & CSR_HW_REV_TYPE_MSK) { + switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { case CSR_HW_REV_TYPE_NONE: IWL_ERR(priv, "Unknown hardware type\n"); return -ENOENT; + case CSR_HW_REV_TYPE_3945: + case CSR_HW_REV_TYPE_4965: case CSR_HW_REV_TYPE_5300: case CSR_HW_REV_TYPE_5350: case CSR_HW_REV_TYPE_5100: @@ -215,20 +217,26 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) return nvm_type; } +const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) +{ + BUG_ON(offset >= priv->cfg->base_params->eeprom_size); + return &priv->eeprom[offset]; +} + static int iwl_init_otp_access(struct iwl_priv *priv) { int ret; /* Enable 40MHz radio clock */ - iwl_write32(priv, CSR_GP_CNTRL, - iwl_read32(priv, CSR_GP_CNTRL) | - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + _iwl_write32(priv, CSR_GP_CNTRL, + _iwl_read32(priv, CSR_GP_CNTRL) | + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ ret = iwl_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - 25000); + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + 25000); if (ret < 0) IWL_ERR(priv, "Time out access OTP\n"); else { @@ -255,17 +263,17 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat u32 r; u32 otpgp; - iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + _iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); + CSR_EEPROM_REG_READ_VALID_MSK, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); return ret; } - r = iwl_read32(priv, CSR_EEPROM_REG); + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); /* check for ECC errors: */ otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { @@ -388,7 +396,7 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) * * NOTE: This routine uses the non-debug IO access functions. */ -int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) +int iwl_eeprom_init(struct iwl_priv *priv) { __le16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); @@ -398,7 +406,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) u16 validblockaddr = 0; u16 cache_addr = 0; - priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); + priv->nvm_device_type = iwlcore_get_nvm_type(priv); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ @@ -436,9 +444,9 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = -ENOENT; goto done; } - iwl_write32(priv, CSR_EEPROM_GP, - iwl_read32(priv, CSR_EEPROM_GP) & - ~CSR_EEPROM_GP_IF_OWNER_MSK); + _iwl_write32(priv, CSR_EEPROM_GP, + iwl_read32(priv, CSR_EEPROM_GP) & + ~CSR_EEPROM_GP_IF_OWNER_MSK); iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | @@ -465,8 +473,8 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + _iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, @@ -476,7 +484,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = iwl_read32(priv, CSR_EEPROM_REG); + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 9ce052573c6a..20b66469d68f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,6 +110,10 @@ enum { }; /* SKU Capabilities */ +/* 3945 only */ +#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) +#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) + /* 5000 and up */ #define EEPROM_SKU_CAP_BAND_POS (4) #define EEPROM_SKU_CAP_BAND_SELECTION \ @@ -164,6 +168,28 @@ struct iwl_eeprom_enhanced_txpwr { s8 mimo3_max; } __packed; +/* 3945 Specific */ +#define EEPROM_3945_EEPROM_VERSION (0x2f) + +/* 4965 has two radio transmitters (and 3 radio receivers) */ +#define EEPROM_TX_POWER_TX_CHAINS (2) + +/* 4965 has room for up to 8 sets of txpower calibration data */ +#define EEPROM_TX_POWER_BANDS (8) + +/* 4965 factory calibration measures txpower gain settings for + * each of 3 target output levels */ +#define EEPROM_TX_POWER_MEASUREMENTS (3) + +/* 4965 Specific */ +/* 4965 driver does not work with txpower calibration version < 5 */ +#define EEPROM_4965_TX_POWER_VERSION (5) +#define EEPROM_4965_EEPROM_VERSION (0x2f) +#define EEPROM_4965_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ +#define EEPROM_4965_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ +#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ +#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ + /* 5000 Specific */ #define EEPROM_5000_TX_POWER_VERSION (4) #define EEPROM_5000_EEPROM_VERSION (0x11A) @@ -256,6 +282,90 @@ struct iwl_eeprom_enhanced_txpwr { /* 2.4 GHz */ extern const u8 iwl_eeprom_band_1[14]; +/* + * factory calibration data for one txpower level, on one channel, + * measured on one of the 2 tx chains (radio transmitter and associated + * antenna). EEPROM contains: + * + * 1) Temperature (degrees Celsius) of device when measurement was made. + * + * 2) Gain table index used to achieve the target measurement power. + * This refers to the "well-known" gain tables (see iwl-4965-hw.h). + * + * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). + * + * 4) RF power amplifier detector level measurement (not used). + */ +struct iwl_eeprom_calib_measure { + u8 temperature; /* Device temperature (Celsius) */ + u8 gain_idx; /* Index into gain table */ + u8 actual_pow; /* Measured RF output power, half-dBm */ + s8 pa_det; /* Power amp detector level (not used) */ +} __packed; + + +/* + * measurement set for one channel. EEPROM contains: + * + * 1) Channel number measured + * + * 2) Measurements for each of 3 power levels for each of 2 radio transmitters + * (a.k.a. "tx chains") (6 measurements altogether) + */ +struct iwl_eeprom_calib_ch_info { + u8 ch_num; + struct iwl_eeprom_calib_measure + measurements[EEPROM_TX_POWER_TX_CHAINS] + [EEPROM_TX_POWER_MEASUREMENTS]; +} __packed; + +/* + * txpower subband info. + * + * For each frequency subband, EEPROM contains the following: + * + * 1) First and last channels within range of the subband. "0" values + * indicate that this sample set is not being used. + * + * 2) Sample measurement sets for 2 channels close to the range endpoints. + */ +struct iwl_eeprom_calib_subband_info { + u8 ch_from; /* channel number of lowest channel in subband */ + u8 ch_to; /* channel number of highest channel in subband */ + struct iwl_eeprom_calib_ch_info ch1; + struct iwl_eeprom_calib_ch_info ch2; +} __packed; + + +/* + * txpower calibration info. EEPROM contains: + * + * 1) Factory-measured saturation power levels (maximum levels at which + * tx power amplifier can output a signal without too much distortion). + * There is one level for 2.4 GHz band and one for 5 GHz band. These + * values apply to all channels within each of the bands. + * + * 2) Factory-measured power supply voltage level. This is assumed to be + * constant (i.e. same value applies to all channels/bands) while the + * factory measurements are being made. + * + * 3) Up to 8 sets of factory-measured txpower calibration values. + * These are for different frequency ranges, since txpower gain + * characteristics of the analog radio circuitry vary with frequency. + * + * Not all sets need to be filled with data; + * struct iwl_eeprom_calib_subband_info contains range of channels + * (0 if unused) for each set of data. + */ +struct iwl_eeprom_calib_info { + u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ + u8 saturation_power52; /* half-dBm */ + __le16 voltage; /* signed */ + struct iwl_eeprom_calib_subband_info + band_info[EEPROM_TX_POWER_BANDS]; +} __packed; + + #define ADDRESS_MSK 0x0000FFFF #define INDIRECT_TYPE_MSK 0x000F0000 #define INDIRECT_HOST 0x00010000 @@ -288,8 +398,83 @@ extern const u8 iwl_eeprom_band_1[14]; #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ +#define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 +#define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 + +/* Radio Config for 5000 and up */ +#define EEPROM_RF_CONFIG_TYPE_R3x3 0x0 +#define EEPROM_RF_CONFIG_TYPE_R2x2 0x1 +#define EEPROM_RF_CONFIG_TYPE_R1x2 0x2 #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 +/* + * Per-channel regulatory data. + * + * Each channel that *might* be supported by iwl has a fixed location + * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory + * txpower (MSB). + * + * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz) + * channels (only for 4965, not supported by 3945) appear later in the EEPROM. + * + * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + */ +#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ +#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ +#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ + +/* + * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, + * 5.0 GHz channels 7, 8, 11, 12, 16 + * (4915-5080MHz) (none of these is ever supported) + */ +#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ +#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ + +/* + * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 + * (5170-5320MHz) + */ +#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ +#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ + +/* + * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 + * (5500-5700MHz) + */ +#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ +#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ + +/* + * 5.7 GHz channels 145, 149, 153, 157, 161, 165 + * (5725-5825MHz) + */ +#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ +#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ + +/* + * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) + * + * The channel listed is the center of the lower 20 MHz half of the channel. + * The overall center frequency is actually 2 channels (10 MHz) above that, + * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away + * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5, + * and the overall HT40 channel width centers on channel 3. + * + * NOTE: The RXON command uses 20 MHz channel numbers to specify the + * control channel to which to tune. RXON also specifies whether the + * control channel is the upper or lower half of a HT40 channel. + * + * NOTE: 4965 does not support HT40 channels on 2.4 GHz. + */ +#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0) /* 14 bytes */ + +/* + * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64), + * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) + */ +#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8) /* 22 bytes */ + #define EEPROM_REGULATORY_BAND_NO_HT40 (0) struct iwl_eeprom_ops { @@ -302,13 +487,14 @@ struct iwl_eeprom_ops { }; -int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); +int iwl_eeprom_init(struct iwl_priv *priv); void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); +const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); int iwl_init_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv); const struct iwl_channel_info *iwl_get_channel_info( diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h index b90924e890a7..55b8370bc6d4 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,14 +77,14 @@ /** * Keep-Warm (KW) buffer base address. * - * Driver must allocate a 4KByte buffer that is for keeping the + * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency - * DRAM access when doing Txing or Rxing. The dummy accesses prevent host + * DRAM access when 4965 is Txing or Rxing. The dummy accesses prevent host * from going into a power-savings mode that would cause higher DRAM latency, * and possible data over/under-runs, before all Tx/Rx is complete. * * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4) - * of the buffer, which must be 4K aligned. Once this is set up, the device + * of the buffer, which must be 4K aligned. Once this is set up, the 4965 * automatically invokes keep-warm accesses when normal accesses might not * be sufficient to maintain fast DRAM response. * @@ -97,7 +97,7 @@ /** * TFD Circular Buffers Base (CBBC) addresses * - * Device has 16 base pointer registers, one for each of 16 host-DRAM-resident + * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs) * (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04 * bytes from one another. Each TFD circular buffer in DRAM must be 256-byte @@ -116,16 +116,16 @@ /** * Rx SRAM Control and Status Registers (RSCSR) * - * These registers provide handshake between driver and device for the Rx queue + * These registers provide handshake between driver and 4965 for the Rx queue * (this queue handles *all* command responses, notifications, Rx data, etc. - * sent from uCode to host driver). Unlike Tx, there is only one Rx + * sent from 4965 uCode to host driver). Unlike Tx, there is only one Rx * queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1 * mapping between RBDs and RBs. * * Driver must allocate host DRAM memory for the following, and set the - * physical address of each into device registers: + * physical address of each into 4965 registers: * * 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256 * entries (although any power of 2, up to 4096, is selectable by driver). @@ -140,20 +140,20 @@ * Driver sets physical address [35:8] of base of RBD circular buffer * into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0]. * - * 2) Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers + * 2) Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers * (RBs) have been filled, via a "write pointer", actually the index of * the RB's corresponding RBD within the circular buffer. Driver sets * physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0]. * * Bit fields in lower dword of Rx status buffer (upper dword not used - * by driver: + * by driver; see struct iwl4965_shared, val0): * 31-12: Not used by driver * 11- 0: Index of last filled Rx buffer descriptor - * (device writes, driver reads this value) + * (4965 writes, driver reads this value) * - * As the driver prepares Receive Buffers (RBs) for device to fill, driver must + * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must * enter pointers to these RBs into contiguous RBD circular buffer entries, - * and update the device's "write" index register, + * and update the 4965's "write" index register, * FH_RSCSR_CHNL0_RBDCB_WPTR_REG. * * This "write" index corresponds to the *next* RBD that the driver will make @@ -162,12 +162,12 @@ * RBs), should be 8 after preparing the first 8 RBs (for example), and must * wrap back to 0 at the end of the circular buffer (but don't wrap before * "read" index has advanced past 1! See below). - * NOTE: DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. + * NOTE: 4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. * - * As the device fills RBs (referenced from contiguous RBDs within the circular + * As the 4965 fills RBs (referenced from contiguous RBDs within the circular * buffer), it updates the Rx status buffer in host DRAM, 2) described above, * to tell the driver the index of the latest filled RBD. The driver must - * read this "read" index from DRAM after receiving an Rx interrupt from device + * read this "read" index from DRAM after receiving an Rx interrupt from 4965. * * The driver must also internally keep track of a third index, which is the * next RBD to process. When receiving an Rx interrupt, driver should process @@ -176,7 +176,7 @@ * driver may process the RB pointed to by RBD 0. Depending on volume of * traffic, there may be many RBs to process. * - * If read index == write index, device thinks there is no room to put new data. + * If read index == write index, 4965 thinks there is no room to put new data. * Due to this, the maximum number of filled RBs is 255, instead of 256. To * be safe, make sure that there is a gap of at least 2 RBDs between "write" * and "read" indexes; that is, make sure that there are no more than 254 @@ -303,7 +303,7 @@ /** * Transmit DMA Channel Control/Status Registers (TCSR) * - * Device has one configuration register for each of 8 Tx DMA/FIFO channels + * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels * supported in hardware (don't confuse these with the 16 Tx queues in DRAM, * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes. * @@ -326,6 +326,7 @@ #define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60) /* Find Control/Status reg for given Tx DMA/FIFO channel */ +#define FH49_TCSR_CHNL_NUM (7) #define FH50_TCSR_CHNL_NUM (8) /* TCSR: tx_config register values */ @@ -423,6 +424,7 @@ #define RX_LOW_WATERMARK 8 /* Size of one Rx buffer in host DRAM */ +#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */ #define IWL_RX_BUF_SIZE_4K (4 * 1024) #define IWL_RX_BUF_SIZE_8K (8 * 1024) @@ -441,7 +443,7 @@ struct iwl_rb_status { __le16 closed_fr_num; __le16 finished_rb_num; __le16 finished_fr_nam; - __le32 __unused; + __le32 __unused; /* 3945 only */ } __packed; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8f0beb992ccf..02499f684683 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -51,7 +51,9 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_REMOVE_ALL_STA); IWL_CMD(REPLY_TXFIFO_FLUSH); IWL_CMD(REPLY_WEPKEY); + IWL_CMD(REPLY_3945_RX); IWL_CMD(REPLY_TX); + IWL_CMD(REPLY_RATE_SCALE); IWL_CMD(REPLY_LEDS_CMD); IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); IWL_CMD(COEX_PRIORITY_TABLE_CMD); @@ -143,12 +145,10 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { int ret; - if (WARN_ON(!(cmd->flags & CMD_ASYNC))) - return -EINVAL; + BUG_ON(!(cmd->flags & CMD_ASYNC)); /* An asynchronous command can not expect an SKB to be set. */ - if (WARN_ON(cmd->flags & CMD_WANT_SKB)) - return -EINVAL; + BUG_ON(cmd->flags & CMD_WANT_SKB); /* Assign a generic callback if one is not provided */ if (!cmd->callback) @@ -171,15 +171,14 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int cmd_idx; int ret; - if (WARN_ON(cmd->flags & CMD_ASYNC)) - return -EINVAL; + BUG_ON(cmd->flags & CMD_ASYNC); /* A synchronous command can not have a callback set. */ - if (WARN_ON(cmd->callback)) - return -EINVAL; + BUG_ON(cmd->callback); IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); + mutex_lock(&priv->sync_cmd_mutex); set_bit(STATUS_HCMD_ACTIVE, &priv->status); IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", @@ -190,7 +189,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ret = cmd_idx; IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); - return ret; + goto out; } ret = wait_event_interruptible_timeout(priv->wait_command_queue, @@ -230,7 +229,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) goto cancel; } - return 0; + ret = 0; + goto out; cancel: if (cmd->flags & CMD_WANT_SKB) { @@ -248,7 +248,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) iwl_free_pages(priv, cmd->reply_page); cmd->reply_page = 0; } - +out: + mutex_unlock(&priv->sync_cmd_mutex); return ret; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h index 41207a3645b8..8821f088ba7f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -64,6 +64,30 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) return --index & (n_bd - 1); } +/* TODO: Move fw_desc functions to iwl-pci.ko */ +static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, + struct fw_desc *desc) +{ + if (desc->v_addr) + dma_free_coherent(&pci_dev->dev, desc->len, + desc->v_addr, desc->p_addr); + desc->v_addr = NULL; + desc->len = 0; +} + +static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, + struct fw_desc *desc) +{ + if (!desc->len) { + desc->v_addr = NULL; + return -EINVAL; + } + + desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, + &desc->p_addr, GFP_KERNEL); + return (desc->v_addr != NULL) ? 0 : -ENOMEM; +} + /* * we have 8 bits used like this: * @@ -107,19 +131,6 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, ieee80211_stop_queue(priv->hw, ac); } -static inline void iwl_wake_any_queue(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) -{ - u8 ac; - - for (ac = 0; ac < AC_NUM; ac++) { - IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", - ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) - ? "stopped" : "awake"); - iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); - } -} - #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.c b/trunk/drivers/net/wireless/iwlwifi/iwl-io.c deleted file mode 100644 index 993b3df1b72b..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.c +++ /dev/null @@ -1,286 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include "iwl-io.h" - -#define IWL_POLL_INTERVAL 10 /* microseconds */ - -static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); -} - -static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); -} - -void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - __iwl_set_bit(priv, reg, mask); - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - __iwl_clear_bit(priv, reg, mask); - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -int iwl_poll_bit(struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int t = 0; - - do { - if ((iwl_read32(priv, addr) & mask) == (bits & mask)) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - -int iwl_grab_nic_access(struct iwl_priv *priv) -{ - int ret; - u32 val; - - lockdep_assert_held(&priv->reg_lock); - - /* this bit wakes up the NIC */ - __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - /* - * These bits say the device is running, and should keep running for - * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), - * but they do not indicate that embedded SRAM is restored yet; - * 3945 and 4965 have volatile SRAM, and must save/restore contents - * to/from host DRAM when sleeping/waking for power-saving. - * Each direction takes approximately 1/4 millisecond; with this - * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a - * series of register accesses are expected (e.g. reading Event Log), - * to keep device from sleeping. - * - * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that - * SRAM is okay/restored. We don't check that here because this call - * is just for hardware register access; but GP1 MAC_SLEEP check is a - * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). - * - * 5000 series and later (including 1000 series) have non-volatile SRAM, - * and do not save/restore SRAM when power cycling. - */ - ret = iwl_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, - (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); - if (ret < 0) { - val = iwl_read32(priv, CSR_GP_CNTRL); - IWL_ERR(priv, - "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); - return -EIO; - } - - return 0; -} - -void iwl_release_nic_access(struct iwl_priv *priv) -{ - lockdep_assert_held(&priv->reg_lock); - __iwl_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -} - -u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - u32 value; - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - value = iwl_read32(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); - - return value; -} - -void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) { - iwl_write32(priv, reg, value); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, - int timeout) -{ - int t = 0; - - do { - if ((iwl_read_direct32(priv, addr) & mask) == mask) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - -static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) -{ - iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); - rmb(); - return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); -} - -static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) -{ - iwl_write32(priv, HBUS_TARG_PRPH_WADDR, - ((addr & 0x0000FFFF) | (3 << 24))); - wmb(); - iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); -} - -u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) -{ - unsigned long flags; - u32 val; - - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - val = __iwl_read_prph(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); - return val; -} - -void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) { - __iwl_write_prph(priv, addr, val); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, - u32 bits, u32 mask) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - __iwl_write_prph(priv, reg, - (__iwl_read_prph(priv, reg) & mask) | bits); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) -{ - unsigned long flags; - u32 val; - - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - val = __iwl_read_prph(priv, reg); - __iwl_write_prph(priv, reg, (val & ~mask)); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, - void *buf, int words) -{ - unsigned long flags; - int offs; - u32 *vals = buf; - - spin_lock_irqsave(&priv->reg_lock, flags); - iwl_grab_nic_access(priv); - - iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); - rmb(); - - for (offs = 0; offs < words; offs++) - vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); -} - -u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) -{ - u32 value; - - _iwl_read_targ_mem_words(priv, addr, &value, 1); - - return value; -} - -void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) { - iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, flags); -} diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h index 262e0262496d..0203a3bbf872 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * @@ -35,57 +35,494 @@ #include "iwl-debug.h" #include "iwl-devtrace.h" -static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) +/* + * IO, register, and NIC memory access functions + * + * NOTE on naming convention and macro usage for these + * + * A single _ prefix before a an access function means that no state + * check or debug information is printed when that function is called. + * + * A double __ prefix before an access function means that state is checked + * and the current line number and caller function name are printed in addition + * to any other debug output. + * + * The non-prefixed name is the #define that maps the caller into a + * #define that provides the caller's name and __LINE__ to the double + * prefix version. + * + * If you wish to call the function without any debug or state checking, + * you should use the single _ prefix version (as is used by dependent IO + * routines, for example _iwl_read_direct32 calls the non-check version of + * _iwl_read32.) + * + * These declarations are *extremely* useful in quickly isolating code deltas + * which result in misconfiguration of the hardware I/O. In combination with + * git-bisect and the IO debug level you can quickly determine the specific + * commit which breaks the IO sequence to the hardware. + * + */ + +static inline void _iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) { trace_iwlwifi_dev_iowrite8(priv, ofs, val); iowrite8(val, priv->hw_base + ofs); } -static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_write8(const char *f, u32 l, struct iwl_priv *priv, + u32 ofs, u8 val) +{ + IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l); + _iwl_write8(priv, ofs, val); +} +#define iwl_write8(priv, ofs, val) \ + __iwl_write8(__FILE__, __LINE__, priv, ofs, val) +#else +#define iwl_write8(priv, ofs, val) _iwl_write8(priv, ofs, val) +#endif + + +static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) { trace_iwlwifi_dev_iowrite32(priv, ofs, val); iowrite32(val, priv->hw_base + ofs); } -static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, + u32 ofs, u32 val) +{ + IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); + _iwl_write32(priv, ofs, val); +} +#define iwl_write32(priv, ofs, val) \ + __iwl_write32(__FILE__, __LINE__, priv, ofs, val) +#else +#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) +#endif + +static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs) { u32 val = ioread32(priv->hw_base + ofs); trace_iwlwifi_dev_ioread32(priv, ofs, val); return val; } -void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); -void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); +#ifdef CONFIG_IWLWIFI_DEBUG +static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) +{ + IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l); + return _iwl_read32(priv, ofs); +} +#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) +#else +#define iwl_read32(p, o) _iwl_read32(p, o) +#endif + +#define IWL_POLL_INTERVAL 10 /* microseconds */ +static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) + return t; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline int __iwl_poll_bit(const char *f, u32 l, + struct iwl_priv *priv, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); + IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", + addr, bits, mask, + unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); + return ret; +} +#define iwl_poll_bit(priv, addr, bits, mask, timeout) \ + __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) +#else +#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) +#endif + +static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_set_bit(const char *f, u32 l, + struct iwl_priv *priv, u32 reg, u32 mask) +{ + u32 val = _iwl_read32(priv, reg) | mask; + IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); + _iwl_write32(priv, reg, val); +} +static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + __iwl_set_bit(__FILE__, __LINE__, p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} +#else +static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + _iwl_set_bit(p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} +#endif + +static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_clear_bit(const char *f, u32 l, + struct iwl_priv *priv, u32 reg, u32 mask) +{ + u32 val = _iwl_read32(priv, reg) & ~mask; + IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); + _iwl_write32(priv, reg, val); +} +static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + __iwl_clear_bit(__FILE__, __LINE__, p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} +#else +static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&p->reg_lock, reg_flags); + _iwl_clear_bit(p, r, m); + spin_unlock_irqrestore(&p->reg_lock, reg_flags); +} +#endif + +static inline int _iwl_grab_nic_access(struct iwl_priv *priv) +{ + int ret; + u32 val; + + /* this bit wakes up the NIC */ + _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + + /* + * These bits say the device is running, and should keep running for + * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), + * but they do not indicate that embedded SRAM is restored yet; + * 3945 and 4965 have volatile SRAM, and must save/restore contents + * to/from host DRAM when sleeping/waking for power-saving. + * Each direction takes approximately 1/4 millisecond; with this + * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a + * series of register accesses are expected (e.g. reading Event Log), + * to keep device from sleeping. + * + * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that + * SRAM is okay/restored. We don't check that here because this call + * is just for hardware register access; but GP1 MAC_SLEEP check is a + * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). + * + * 5000 series and later (including 1000 series) have non-volatile SRAM, + * and do not save/restore SRAM when power cycling. + */ + ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, + (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | + CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); + if (ret < 0) { + val = _iwl_read32(priv, CSR_GP_CNTRL); + IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); + _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); + return -EIO; + } + + return 0; +} + +#ifdef CONFIG_IWLWIFI_DEBUG +static inline int __iwl_grab_nic_access(const char *f, u32 l, + struct iwl_priv *priv) +{ + IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); + return _iwl_grab_nic_access(priv); +} +#define iwl_grab_nic_access(priv) \ + __iwl_grab_nic_access(__FILE__, __LINE__, priv) +#else +#define iwl_grab_nic_access(priv) \ + _iwl_grab_nic_access(priv) +#endif + +static inline void _iwl_release_nic_access(struct iwl_priv *priv) +{ + _iwl_clear_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_release_nic_access(const char *f, u32 l, + struct iwl_priv *priv) +{ + + IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); + _iwl_release_nic_access(priv); +} +#define iwl_release_nic_access(priv) \ + __iwl_release_nic_access(__FILE__, __LINE__, priv) +#else +#define iwl_release_nic_access(priv) \ + _iwl_release_nic_access(priv) +#endif + +static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + return _iwl_read32(priv, reg); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline u32 __iwl_read_direct32(const char *f, u32 l, + struct iwl_priv *priv, u32 reg) +{ + u32 value = _iwl_read_direct32(priv, reg); + IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, + f, l); + return value; +} +static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + u32 value; + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return value; +} + +#else +static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + u32 value; + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + value = _iwl_read_direct32(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return value; + +} +#endif + +static inline void _iwl_write_direct32(struct iwl_priv *priv, + u32 reg, u32 value) +{ + _iwl_write32(priv, reg, value); +} +static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_direct32(priv, reg, value); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} + +static inline void iwl_write_reg_buf(struct iwl_priv *priv, + u32 reg, u32 len, u32 *values) +{ + u32 count = sizeof(u32); + + if ((priv != NULL) && (values != NULL)) { + for (; 0 < len; len -= count, reg += count, values++) + iwl_write_direct32(priv, reg, *values); + } +} + +static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, + u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_read_direct32(priv, addr) & mask) == mask) + return t; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + +#ifdef CONFIG_IWLWIFI_DEBUG +static inline int __iwl_poll_direct_bit(const char *f, u32 l, + struct iwl_priv *priv, + u32 addr, u32 mask, int timeout) +{ + int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); + + if (unlikely(ret == -ETIMEDOUT)) + IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - " + "timedout - %s %d\n", addr, mask, f, l); + else + IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " + "- %s %d\n", addr, mask, ret, f, l); + return ret; +} +#define iwl_poll_direct_bit(priv, addr, mask, timeout) \ + __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) +#else +#define iwl_poll_direct_bit _iwl_poll_direct_bit +#endif + +static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) +{ + _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + rmb(); + return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); +} +static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) +{ + unsigned long reg_flags; + u32 val; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + val = _iwl_read_prph(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return val; +} + +static inline void _iwl_write_prph(struct iwl_priv *priv, + u32 addr, u32 val) +{ + _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR, + ((addr & 0x0000FFFF) | (3 << 24))); + wmb(); + _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); +} + +static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_prph(priv, addr, val); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} + +#define _iwl_set_bits_prph(priv, reg, mask) \ + _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) + +static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + _iwl_set_bits_prph(priv, reg, mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} + +#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ + _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) -int iwl_poll_bit(struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout); -int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, - int timeout); +static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, + u32 bits, u32 mask) +{ + unsigned long reg_flags; -int iwl_grab_nic_access(struct iwl_priv *priv); -void iwl_release_nic_access(struct iwl_priv *priv); + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + _iwl_set_bits_mask_prph(priv, reg, bits, mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} -u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); -void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); +static inline void iwl_clear_bits_prph(struct iwl_priv + *priv, u32 reg, u32 mask) +{ + unsigned long reg_flags; + u32 val; + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + val = _iwl_read_prph(priv, reg); + _iwl_write_prph(priv, reg, (val & ~mask)); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} + +static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) +{ + unsigned long reg_flags; + u32 value; -u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); -void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); -void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, - u32 bits, u32 mask); -void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); -void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, - void *buf, int words); + _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); + rmb(); + value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ - do { \ - BUILD_BUG_ON((bufsize) % sizeof(u32)); \ - _iwl_read_targ_mem_words(priv, addr, buf, \ - (bufsize) / sizeof(u32));\ - } while (0) + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return value; +} -u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); -void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); +static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); + wmb(); + _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} + +static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, + u32 len, u32 *values) +{ + unsigned long reg_flags; + + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (!iwl_grab_nic_access(priv)) { + _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); + wmb(); + for (; 0 < len; len -= sizeof(u32), values++) + _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); + + iwl_release_nic_access(priv); + } + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} #endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c index d798c2a152d3..d7f2a0bb32c9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -61,16 +61,10 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { { .throughput = 300 * 1024 - 1, .blink_time = 50 }, }; -/* Set led register off */ -void iwlagn_led_enable(struct iwl_priv *priv) -{ - iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); -} - /* * Adjust led blink rate to compensate on a MAC Clock difference on every HW - * Led blink rate analysis showed an average deviation of 20% on 5000 series - * and up. + * Led blink rate analysis showed an average deviation of 0% on 3945, + * 5% on 4965 HW and 20% on 5000 series and up. * Need to compensate on the led on/off time per HW according to the deviation * to achieve the desired led frequency * The calculation is: (100-averageDeviation)/100 * blinkTime @@ -90,24 +84,6 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv, return (u8)((time * compensation) >> 6); } -static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl_led_cmd), - .data = led_cmd, - .flags = CMD_ASYNC, - .callback = NULL, - }; - u32 reg; - - reg = iwl_read32(priv, CSR_LED_REG); - if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - - return iwl_send_cmd(priv, &cmd); -} - /* Set led pattern command */ static int iwl_led_cmd(struct iwl_priv *priv, unsigned long on, @@ -132,7 +108,7 @@ static int iwl_led_cmd(struct iwl_priv *priv, led_cmd.off = iwl_blink_compensation(priv, off, priv->cfg->base_params->led_compensation); - ret = iwl_send_led_cmd(priv, &led_cmd); + ret = priv->cfg->ops->led->cmd(priv, &led_cmd); if (!ret) { priv->blink_on = on; priv->blink_off = off; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.h b/trunk/drivers/net/wireless/iwlwifi/iwl-led.h index 1c93dfef6933..101eef12b3bb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -50,7 +50,6 @@ enum iwl_led_mode { IWL_LED_BLINK, }; -void iwlagn_led_enable(struct iwl_priv *priv); void iwl_leds_init(struct iwl_priv *priv); void iwl_leds_exit(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c index 595c930b28ae..576795e2c75b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -188,10 +188,9 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, table = range_0; } - if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM)) - memset(cmd, 0, sizeof(*cmd)); - else - *cmd = table[lvl].cmd; + BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); + + *cmd = table[lvl].cmd; if (period == 0) { skip = 0; @@ -355,12 +354,16 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) + if (priv->cfg->base_params->broken_powersave) + iwl_power_sleep_cam_cmd(priv, cmd); + else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); - else if (iwl_tt_is_low_power_state(priv)) { + else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && + priv->cfg->ops->lib->tt_ops.tt_power_mode && + priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { /* in thermal throttling low power state */ iwl_static_sleep_cmd(priv, cmd, - iwl_tt_current_power_mode(priv), dtimper); + priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); } else if (!enabled) iwl_power_sleep_cam_cmd(priv, cmd); else if (priv->power_data.debug_sleep_level_override >= 0) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-power.h b/trunk/drivers/net/wireless/iwlwifi/iwl-power.h index 59635d784e27..fe012032c28c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-power.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h index f00d188b2cfc..86f5123bccda 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -91,12 +91,159 @@ #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_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) +/** + * BSM (Bootstrap State Machine) + * + * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program + * in special SRAM that does not power down when the embedded control + * processor is sleeping (e.g. for periodic power-saving shutdowns of radio). + * + * When powering back up after sleeps (or during initial uCode load), the BSM + * internally loads the short bootstrap program from the special SRAM into the + * embedded processor's instruction SRAM, and starts the processor so it runs + * the bootstrap program. + * + * This bootstrap program loads (via PCI busmaster DMA) instructions and data + * images for a uCode program from host DRAM locations. The host driver + * indicates DRAM locations and sizes for instruction and data images via the + * four BSM_DRAM_* registers. Once the bootstrap program loads the new program, + * the new program starts automatically. + * + * The uCode used for open-source drivers includes two programs: + * + * 1) Initialization -- performs hardware calibration and sets up some + * internal data, then notifies host via "initialize alive" notification + * (struct iwl_init_alive_resp) that it has completed all of its work. + * After signal from host, it then loads and starts the runtime program. + * The initialization program must be used when initially setting up the + * NIC after loading the driver. + * + * 2) Runtime/Protocol -- performs all normal runtime operations. This + * notifies host via "alive" notification (struct iwl_alive_resp) that it + * is ready to be used. + * + * When initializing the NIC, the host driver does the following procedure: + * + * 1) Load bootstrap program (instructions only, no data image for bootstrap) + * into bootstrap memory. Use dword writes starting at BSM_SRAM_LOWER_BOUND + * + * 2) Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction + * images in host DRAM. + * + * 3) Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked: + * BSM_WR_MEM_SRC_REG = 0 + * BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND + * BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image + * + * 4) Load bootstrap into instruction SRAM: + * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START + * + * 5) Wait for load completion: + * Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0 + * + * 6) Enable future boot loads whenever NIC's power management triggers it: + * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN + * + * 7) Start the NIC by removing all reset bits: + * CSR_RESET = 0 + * + * The bootstrap uCode (already in instruction SRAM) loads initialization + * uCode. Initialization uCode performs data initialization, sends + * "initialize alive" notification to host, and waits for a signal from + * host to load runtime code. + * + * 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction + * images in host DRAM. The last register loaded must be the instruction + * byte count register ("1" in MSbit tells initialization uCode to load + * the runtime uCode): + * BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD + * + * 5) Wait for "alive" notification, then issue normal runtime commands. + * + * Data caching during power-downs: + * + * Just before the embedded controller powers down (e.g for automatic + * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA) + * a current snapshot of the embedded processor's data SRAM into host DRAM. + * This caches the data while the embedded processor's memory is powered down. + * Location and size are controlled by BSM_DRAM_DATA_* registers. + * + * NOTE: Instruction SRAM does not need to be saved, since that doesn't + * change during operation; the original image (from uCode distribution + * file) can be used for reload. + * + * When powering back up, the BSM loads the bootstrap program. Bootstrap looks + * at the BSM_DRAM_* registers, which now point to the runtime instruction + * image and the cached (modified) runtime data (*not* the initialization + * uCode). Bootstrap reloads these runtime images into SRAM, and restarts the + * uCode from where it left off before the power-down. + * + * NOTE: Initialization uCode does *not* run as part of the save/restore + * procedure. + * + * This save/restore method is mostly for autonomous power management during + * normal operation (result of POWER_TABLE_CMD). Platform suspend/resume and + * RFKILL should use complete restarts (with total re-initialization) of uCode, + * allowing total shutdown (including BSM memory). + * + * Note that, during normal operation, the host DRAM that held the initial + * startup data for the runtime code is now being used as a backup data cache + * for modified data! If you need to completely re-initialize the NIC, make + * sure that you use the runtime data image from the uCode distribution file, + * not the modified/saved runtime data. You may want to store a separate + * "clean" runtime data image in DRAM to avoid disk reads of distribution file. + */ + +/* BSM bit fields */ +#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */ +#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup*/ +#define BSM_DRAM_INST_LOAD (0x80000000) /* start program load now */ + +/* BSM addresses */ +#define BSM_BASE (PRPH_BASE + 0x3400) +#define BSM_END (PRPH_BASE + 0x3800) + +#define BSM_WR_CTRL_REG (BSM_BASE + 0x000) /* ctl and status */ +#define BSM_WR_MEM_SRC_REG (BSM_BASE + 0x004) /* source in BSM mem */ +#define BSM_WR_MEM_DST_REG (BSM_BASE + 0x008) /* dest in SRAM mem */ +#define BSM_WR_DWCOUNT_REG (BSM_BASE + 0x00C) /* bytes */ +#define BSM_WR_STATUS_REG (BSM_BASE + 0x010) /* bit 0: 1 == done */ + +/* + * Pointers and size regs for bootstrap load and data SRAM save/restore. + * NOTE: 3945 pointers use bits 31:0 of DRAM address. + * 4965 pointers use bits 35:4 of DRAM address. + */ +#define BSM_DRAM_INST_PTR_REG (BSM_BASE + 0x090) +#define BSM_DRAM_INST_BYTECOUNT_REG (BSM_BASE + 0x094) +#define BSM_DRAM_DATA_PTR_REG (BSM_BASE + 0x098) +#define BSM_DRAM_DATA_BYTECOUNT_REG (BSM_BASE + 0x09C) + +/* + * BSM special memory, stays powered on during power-save sleeps. + * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1) + */ +#define BSM_SRAM_LOWER_BOUND (PRPH_BASE + 0x3800) +#define BSM_SRAM_SIZE (1024) /* bytes */ + + +/* 3945 Tx scheduler registers */ +#define ALM_SCD_BASE (PRPH_BASE + 0x2E00) +#define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000) +#define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004) +#define ALM_SCD_TXFACT_REG (ALM_SCD_BASE + 0x010) +#define ALM_SCD_TXF4MF_REG (ALM_SCD_BASE + 0x014) +#define ALM_SCD_TXF5MF_REG (ALM_SCD_BASE + 0x020) +#define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C) +#define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030) + /** * Tx Scheduler * @@ -107,7 +254,17 @@ * device. A queue maps to only one (selectable by driver) Tx DMA channel, * but one DMA channel may take input from several queues. * - * Tx DMA FIFOs have dedicated purposes. + * Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows + * (cf. default_queue_to_tx_fifo in iwl-4965.c): + * + * 0 -- EDCA BK (background) frames, lowest priority + * 1 -- EDCA BE (best effort) frames, normal priority + * 2 -- EDCA VI (video) frames, higher priority + * 3 -- EDCA VO (voice) and management frames, highest priority + * 4 -- Commands (e.g. RXON, etc.) + * 5 -- unused (HCCA) + * 6 -- unused (HCCA) + * 7 -- not used by driver (device-internal only) * * For 5000 series and up, they are used differently * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): @@ -141,7 +298,7 @@ * Tx completion may end up being out-of-order). * * The driver must maintain the queue's Byte Count table in host DRAM - * for this mode. + * (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode. * This mode does not support fragmentation. * * 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order. @@ -154,7 +311,7 @@ * * Driver controls scheduler operation via 3 means: * 1) Scheduler registers - * 2) Shared scheduler data base in internal SRAM + * 2) Shared scheduler data base in internal 4956 SRAM * 3) Shared data in host DRAM * * Initialization: @@ -173,10 +330,201 @@ * Max Tx window size is the max number of contiguous TFDs that the scheduler * can keep track of at one time when creating block-ack chains of frames. * Note that "64" matches the number of ack bits in a block-ack packet. + * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize + * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values. */ #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 +/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */ +#define IWL49_SCD_START_OFFSET 0xa02c00 + +/* + * 4965 tells driver SRAM address for internal scheduler structs via this reg. + * Value is valid only after "Alive" response from uCode. + */ +#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x0) + +/* + * Driver may need to update queue-empty bits after changing queue's + * write and read pointers (indexes) during (re-)initialization (i.e. when + * scheduler is not tracking what's happening). + * Bit fields: + * 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit + * 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty + * NOTE: This register is not used by Linux driver. + */ +#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_START_OFFSET + 0x4) + +/* + * Physical base address of array of byte count (BC) circular buffers (CBs). + * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode. + * This register points to BC CB for queue 0, must be on 1024-byte boundary. + * Others are spaced by 1024 bytes. + * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad. + * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff). + * Bit fields: + * 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned. + */ +#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x10) + +/* + * Enables any/all Tx DMA/FIFO channels. + * Scheduler generates requests for only the active channels. + * Set this to 0xff to enable all 8 channels (normal usage). + * Bit fields: + * 7- 0: Enable (1), disable (0), one bit for each channel 0-7 + */ +#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c) +/* + * Queue (x) Write Pointers (indexes, really!), one for each Tx queue. + * Initialized and updated by driver as new TFDs are added to queue. + * NOTE: If using Block Ack, index must correspond to frame's + * Start Sequence Number; index = (SSN & 0xff) + * NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses? + */ +#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4) + +/* + * Queue (x) Read Pointers (indexes, really!), one for each Tx queue. + * For FIFO mode, index indicates next frame to transmit. + * For Scheduler-ACK mode, index indicates first frame in Tx window. + * Initialized by driver, updated by scheduler. + */ +#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4) + +/* + * Select which queues work in chain mode (1) vs. not (0). + * Use chain mode to build chains of aggregated frames. + * Bit fields: + * 31-16: Reserved + * 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time + * NOTE: If driver sets up queue for chain mode, it should be also set up + * Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x). + */ +#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_START_OFFSET + 0xd0) + +/* + * Select which queues interrupt driver when scheduler increments + * a queue's read pointer (index). + * Bit fields: + * 31-16: Reserved + * 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled + * NOTE: This functionality is apparently a no-op; driver relies on interrupts + * from Rx queue to read Tx command responses and update Tx queues. + */ +#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_START_OFFSET + 0xe4) + +/* + * Queue search status registers. One for each queue. + * Sets up queue mode and assigns queue to Tx DMA channel. + * Bit fields: + * 19-10: Write mask/enable bits for bits 0-9 + * 9: Driver should init to "0" + * 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0). + * Driver should init to "1" for aggregation mode, or "0" otherwise. + * 7-6: Driver should init to "0" + * 5: Window Size Left; indicates whether scheduler can request + * another TFD, based on window size, etc. Driver should init + * this bit to "1" for aggregation mode, or "0" for non-agg. + * 4-1: Tx FIFO to use (range 0-7). + * 0: Queue is active (1), not active (0). + * Other bits should be written as "0" + * + * NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled + * via SCD_QUEUECHAIN_SEL. + */ +#define IWL49_SCD_QUEUE_STATUS_BITS(x)\ + (IWL49_SCD_START_OFFSET + 0x104 + (x) * 4) + +/* Bit field positions */ +#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE (0) +#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF (1) +#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL (5) +#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK (8) + +/* Write masks */ +#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10) +#define IWL49_SCD_QUEUE_STTS_REG_MSK (0x0007FC00) + +/** + * 4965 internal SRAM structures for scheduler, shared with driver ... + * + * Driver should clear and initialize the following areas after receiving + * "Alive" response from 4965 uCode, i.e. after initial + * uCode load, or after a uCode load done for error recovery: + * + * SCD_CONTEXT_DATA_OFFSET (size 128 bytes) + * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes) + * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes) + * + * Driver accesses SRAM via HBUS_TARG_MEM_* registers. + * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR. + * All OFFSET values must be added to this base address. + */ + +/* + * Queue context. One 8-byte entry for each of 16 queues. + * + * Driver should clear this entire area (size 0x80) to 0 after receiving + * "Alive" notification from uCode. Additionally, driver should init + * each queue's entry as follows: + * + * LS Dword bit fields: + * 0-06: Max Tx window size for Scheduler-ACK. Driver should init to 64. + * + * MS Dword bit fields: + * 16-22: Frame limit. Driver should init to 10 (0xa). + * + * Driver should init all other bits to 0. + * + * Init must be done after driver receives "Alive" response from 4965 uCode, + * and when setting up queue for aggregation. + */ +#define IWL49_SCD_CONTEXT_DATA_OFFSET 0x380 +#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \ + (IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) + +#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0) +#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F) +#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) +#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) + +/* + * Tx Status Bitmap + * + * Driver should clear this entire area (size 0x100) to 0 after receiving + * "Alive" notification from uCode. Area is used only by device itself; + * no other support (besides clearing) is required from driver. + */ +#define IWL49_SCD_TX_STTS_BITMAP_OFFSET 0x400 + +/* + * RAxTID to queue translation mapping. + * + * When queue is in Scheduler-ACK mode, frames placed in a that queue must be + * for only one combination of receiver address (RA) and traffic ID (TID), i.e. + * one QOS priority level destined for one station (for this wireless link, + * not final destination). The SCD_TRANSLATE_TABLE area provides 16 16-bit + * mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK + * mode, the device ignores the mapping value. + * + * Bit fields, for each 16-bit map: + * 15-9: Reserved, set to 0 + * 8-4: Index into device's station table for recipient station + * 3-0: Traffic ID (tid), range 0-15 + * + * Driver should clear this entire area (size 32 bytes) to 0 after receiving + * "Alive" notification from uCode. To update a 16-bit map value, driver + * must read a dword-aligned value from device SRAM, replace the 16-bit map + * value of interest, and write the dword value back into device SRAM. + */ +#define IWL49_SCD_TRANSLATE_TBL_OFFSET 0x500 + +/* Find translation table dword to read/write for given queue */ +#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ + ((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc) + #define IWL_SCD_TXFIFO_POS_TID (0) #define IWL_SCD_TXFIFO_POS_RA (4) #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c index aca9a1d40080..6f9a2fa04763 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -225,6 +225,55 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) * ******************************************************************************/ +static void iwl_rx_reply_alive(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_alive_resp *palive; + struct delayed_work *pwork; + + palive = &pkt->u.alive_frame; + + IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " + "0x%01X 0x%01X\n", + palive->is_valid, palive->ver_type, + palive->ver_subtype); + + if (palive->ver_subtype == INITIALIZE_SUBTYPE) { + IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); + memcpy(&priv->card_alive_init, + &pkt->u.alive_frame, + sizeof(struct iwl_init_alive_resp)); + pwork = &priv->init_alive_start; + } else { + IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); + memcpy(&priv->card_alive, &pkt->u.alive_frame, + sizeof(struct iwl_alive_resp)); + pwork = &priv->alive_start; + } + + /* We delay the ALIVE response by 5ms to + * give the HW RF Kill time to activate... */ + if (palive->is_valid == UCODE_VALID_OK) + queue_delayed_work(priv->workqueue, pwork, + msecs_to_jiffies(5)); + else { + IWL_WARN(priv, "%s uCode did not respond OK.\n", + (palive->ver_subtype == INITIALIZE_SUBTYPE) ? + "init" : "runtime"); + /* + * If fail to load init uCode, + * let's try to load the init uCode again. + * We should not get into this situation, but if it + * does happen, we should not move on and loading "runtime" + * without proper calibrate the device. + */ + if (palive->ver_subtype == INITIALIZE_SUBTYPE) + priv->ucode_type = UCODE_NONE; + queue_work(priv->workqueue, &priv->restart); + } +} + static void iwl_rx_reply_error(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -341,16 +390,21 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal * operation state. */ -static bool iwl_good_ack_health(struct iwl_priv *priv, - struct statistics_tx *cur) +static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt) { int actual_delta, expected_delta, ba_timeout_delta; - struct statistics_tx *old; + struct statistics_tx *cur, *old; if (priv->_agn.agg_tids_count) return true; - old = &priv->statistics.tx; + if (iwl_bt_statistics(priv)) { + cur = &pkt->u.stats_bt.tx; + old = &priv->_agn.statistics_bt.tx; + } else { + cur = &pkt->u.stats.tx; + old = &priv->_agn.statistics.tx; + } actual_delta = le32_to_cpu(cur->actual_ack_cnt) - le32_to_cpu(old->actual_ack_cnt); @@ -376,10 +430,10 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, * DEBUG is not, these will just compile out. */ IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n", - priv->delta_stats.tx.rx_detected_cnt); + priv->_agn.delta_statistics.tx.rx_detected_cnt); IWL_DEBUG_RADIO(priv, "ack_or_ba_timeout_collision delta %d\n", - priv->delta_stats.tx.ack_or_ba_timeout_collision); + priv->_agn.delta_statistics.tx.ack_or_ba_timeout_collision); #endif if (ba_timeout_delta >= BA_TIMEOUT_MAX) @@ -396,9 +450,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, * to improve the throughput. */ static bool iwl_good_plcp_health(struct iwl_priv *priv, - struct statistics_rx_phy *cur_ofdm, - struct statistics_rx_ht_phy *cur_ofdm_ht, - unsigned int msecs) + struct iwl_rx_packet *pkt, unsigned int msecs) { int delta; int threshold = priv->cfg->base_params->plcp_delta_threshold; @@ -408,12 +460,29 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv, return true; } - delta = le32_to_cpu(cur_ofdm->plcp_err) - - le32_to_cpu(priv->statistics.rx_ofdm.plcp_err) + - le32_to_cpu(cur_ofdm_ht->plcp_err) - - le32_to_cpu(priv->statistics.rx_ofdm_ht.plcp_err); + if (iwl_bt_statistics(priv)) { + struct statistics_rx_bt *cur, *old; + + cur = &pkt->u.stats_bt.rx; + old = &priv->_agn.statistics_bt.rx; - /* Can be negative if firmware reset statistics */ + delta = le32_to_cpu(cur->ofdm.plcp_err) - + le32_to_cpu(old->ofdm.plcp_err) + + le32_to_cpu(cur->ofdm_ht.plcp_err) - + le32_to_cpu(old->ofdm_ht.plcp_err); + } else { + struct statistics_rx *cur, *old; + + cur = &pkt->u.stats.rx; + old = &priv->_agn.statistics.rx; + + delta = le32_to_cpu(cur->ofdm.plcp_err) - + le32_to_cpu(old->ofdm.plcp_err) + + le32_to_cpu(cur->ofdm_ht.plcp_err) - + le32_to_cpu(old->ofdm_ht.plcp_err); + } + + /* Can be negative if firmware reseted statistics */ if (delta <= 0) return true; @@ -428,36 +497,44 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv, } static void iwl_recover_from_statistics(struct iwl_priv *priv, - struct statistics_rx_phy *cur_ofdm, - struct statistics_rx_ht_phy *cur_ofdm_ht, - struct statistics_tx *tx, - unsigned long stamp) + struct iwl_rx_packet *pkt) { const struct iwl_mod_params *mod_params = priv->cfg->mod_params; unsigned int msecs; + unsigned long stamp; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + stamp = jiffies; msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); /* Only gather statistics and update time stamp when not associated */ if (!iwl_is_any_associated(priv)) - return; + goto out; /* Do not check/recover when do not have enough statistics data */ if (msecs < 99) return; - if (mod_params->ack_check && !iwl_good_ack_health(priv, tx)) { + if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) { IWL_ERR(priv, "low ack count detected, restart firmware\n"); if (!iwl_force_reset(priv, IWL_FW_RESET, false)) return; } - if (mod_params->plcp_check && - !iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) + if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs)) iwl_force_reset(priv, IWL_RF_RESET, false); + +out: + if (iwl_bt_statistics(priv)) + memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, + sizeof(priv->_agn.statistics_bt)); + else + memcpy(&priv->_agn.statistics, &pkt->u.stats, + sizeof(priv->_agn.statistics)); + + priv->rx_statistics_jiffies = stamp; } /* Calculate noise level, based on measurements during network silence just @@ -471,8 +548,10 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) int bcn_silence_a, bcn_silence_b, bcn_silence_c; int last_rx_noise; - rx_info = &priv->statistics.rx_non_phy; - + if (iwl_bt_statistics(priv)) + rx_info = &(priv->_agn.statistics_bt.rx.general.common); + else + rx_info = &(priv->_agn.statistics.rx.general); bcn_silence_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; bcn_silence_b = @@ -504,153 +583,105 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) last_rx_noise); } -#ifdef CONFIG_IWLWIFI_DEBUGFS /* * based on the assumption of all statistics counter are in DWORD * FIXME: This function is for debugging, do not deal with * the case of counters roll-over. */ -static void accum_stats(__le32 *prev, __le32 *cur, __le32 *delta, - __le32 *max_delta, __le32 *accum, int size) +static void iwl_accumulative_statistics(struct iwl_priv *priv, + __le32 *stats) { - int i; - - for (i = 0; - i < size / sizeof(__le32); - i++, prev++, cur++, delta++, max_delta++, accum++) { - if (le32_to_cpu(*cur) > le32_to_cpu(*prev)) { - *delta = cpu_to_le32( - le32_to_cpu(*cur) - le32_to_cpu(*prev)); - le32_add_cpu(accum, le32_to_cpu(*delta)); - if (le32_to_cpu(*delta) > le32_to_cpu(*max_delta)) +#ifdef CONFIG_IWLWIFI_DEBUGFS + int i, size; + __le32 *prev_stats; + u32 *accum_stats; + u32 *delta, *max_delta; + struct statistics_general_common *general, *accum_general; + struct statistics_tx *tx, *accum_tx; + + if (iwl_bt_statistics(priv)) { + prev_stats = (__le32 *)&priv->_agn.statistics_bt; + accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; + size = sizeof(struct iwl_bt_notif_statistics); + general = &priv->_agn.statistics_bt.general.common; + accum_general = &priv->_agn.accum_statistics_bt.general.common; + tx = &priv->_agn.statistics_bt.tx; + accum_tx = &priv->_agn.accum_statistics_bt.tx; + delta = (u32 *)&priv->_agn.delta_statistics_bt; + max_delta = (u32 *)&priv->_agn.max_delta_bt; + } else { + prev_stats = (__le32 *)&priv->_agn.statistics; + accum_stats = (u32 *)&priv->_agn.accum_statistics; + size = sizeof(struct iwl_notif_statistics); + general = &priv->_agn.statistics.general.common; + accum_general = &priv->_agn.accum_statistics.general.common; + tx = &priv->_agn.statistics.tx; + accum_tx = &priv->_agn.accum_statistics.tx; + delta = (u32 *)&priv->_agn.delta_statistics; + max_delta = (u32 *)&priv->_agn.max_delta; + } + for (i = sizeof(__le32); i < size; + i += sizeof(__le32), stats++, prev_stats++, delta++, + max_delta++, accum_stats++) { + if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { + *delta = (le32_to_cpu(*stats) - + le32_to_cpu(*prev_stats)); + *accum_stats += *delta; + if (*delta > *max_delta) *max_delta = *delta; } } -} -static void -iwl_accumulative_statistics(struct iwl_priv *priv, - struct statistics_general_common *common, - struct statistics_rx_non_phy *rx_non_phy, - struct statistics_rx_phy *rx_ofdm, - struct statistics_rx_ht_phy *rx_ofdm_ht, - struct statistics_rx_phy *rx_cck, - struct statistics_tx *tx, - struct statistics_bt_activity *bt_activity) -{ -#define ACCUM(_name) \ - accum_stats((__le32 *)&priv->statistics._name, \ - (__le32 *)_name, \ - (__le32 *)&priv->delta_stats._name, \ - (__le32 *)&priv->max_delta_stats._name, \ - (__le32 *)&priv->accum_stats._name, \ - sizeof(*_name)); - - ACCUM(common); - ACCUM(rx_non_phy); - ACCUM(rx_ofdm); - ACCUM(rx_ofdm_ht); - ACCUM(rx_cck); - ACCUM(tx); - if (bt_activity) - ACCUM(bt_activity); -#undef ACCUM -} -#else -static inline void -iwl_accumulative_statistics(struct iwl_priv *priv, - struct statistics_general_common *common, - struct statistics_rx_non_phy *rx_non_phy, - struct statistics_rx_phy *rx_ofdm, - struct statistics_rx_ht_phy *rx_ofdm_ht, - struct statistics_rx_phy *rx_cck, - struct statistics_tx *tx, - struct statistics_bt_activity *bt_activity) -{ -} + /* reset accumulative statistics for "no-counter" type statistics */ + accum_general->temperature = general->temperature; + accum_general->temperature_m = general->temperature_m; + accum_general->ttl_timestamp = general->ttl_timestamp; + accum_tx->tx_power.ant_a = tx->tx_power.ant_a; + accum_tx->tx_power.ant_b = tx->tx_power.ant_b; + accum_tx->tx_power.ant_c = tx->tx_power.ant_c; #endif +} static void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { - unsigned long stamp = jiffies; const int reg_recalib_period = 60; int change; struct iwl_rx_packet *pkt = rxb_addr(rxb); - u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - __le32 *flag; - struct statistics_general_common *common; - struct statistics_rx_non_phy *rx_non_phy; - struct statistics_rx_phy *rx_ofdm; - struct statistics_rx_ht_phy *rx_ofdm_ht; - struct statistics_rx_phy *rx_cck; - struct statistics_tx *tx; - struct statistics_bt_activity *bt_activity; - - len -= sizeof(struct iwl_cmd_header); /* skip header */ - - IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", - len); - - if (len == sizeof(struct iwl_bt_notif_statistics)) { - struct iwl_bt_notif_statistics *stats; - stats = &pkt->u.stats_bt; - flag = &stats->flag; - common = &stats->general.common; - rx_non_phy = &stats->rx.general.common; - rx_ofdm = &stats->rx.ofdm; - rx_ofdm_ht = &stats->rx.ofdm_ht; - rx_cck = &stats->rx.cck; - tx = &stats->tx; - bt_activity = &stats->general.activity; -#ifdef CONFIG_IWLWIFI_DEBUGFS - /* handle this exception directly */ - priv->statistics.num_bt_kills = stats->rx.general.num_bt_kills; - le32_add_cpu(&priv->statistics.accum_num_bt_kills, - le32_to_cpu(stats->rx.general.num_bt_kills)); -#endif - } else if (len == sizeof(struct iwl_notif_statistics)) { - struct iwl_notif_statistics *stats; - stats = &pkt->u.stats; - flag = &stats->flag; - common = &stats->general.common; - rx_non_phy = &stats->rx.general; - rx_ofdm = &stats->rx.ofdm; - rx_ofdm_ht = &stats->rx.ofdm_ht; - rx_cck = &stats->rx.cck; - tx = &stats->tx; - bt_activity = NULL; + if (iwl_bt_statistics(priv)) { + IWL_DEBUG_RX(priv, + "Statistics notification received (%d vs %d).\n", + (int)sizeof(struct iwl_bt_notif_statistics), + le32_to_cpu(pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK); + + change = ((priv->_agn.statistics_bt.general.common.temperature != + pkt->u.stats_bt.general.common.temperature) || + ((priv->_agn.statistics_bt.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats_bt.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK))); + + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); } else { - WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", - len, sizeof(struct iwl_bt_notif_statistics), - sizeof(struct iwl_notif_statistics)); - return; + IWL_DEBUG_RX(priv, + "Statistics notification received (%d vs %d).\n", + (int)sizeof(struct iwl_notif_statistics), + le32_to_cpu(pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK); + + change = ((priv->_agn.statistics.general.common.temperature != + pkt->u.stats.general.common.temperature) || + ((priv->_agn.statistics.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK))); + + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); } - change = common->temperature != priv->statistics.common.temperature || - (*flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK); - - iwl_accumulative_statistics(priv, common, rx_non_phy, rx_ofdm, - rx_ofdm_ht, rx_cck, tx, bt_activity); - - iwl_recover_from_statistics(priv, rx_ofdm, rx_ofdm_ht, tx, stamp); - - priv->statistics.flag = *flag; - memcpy(&priv->statistics.common, common, sizeof(*common)); - memcpy(&priv->statistics.rx_non_phy, rx_non_phy, sizeof(*rx_non_phy)); - memcpy(&priv->statistics.rx_ofdm, rx_ofdm, sizeof(*rx_ofdm)); - memcpy(&priv->statistics.rx_ofdm_ht, rx_ofdm_ht, sizeof(*rx_ofdm_ht)); - memcpy(&priv->statistics.rx_cck, rx_cck, sizeof(*rx_cck)); - memcpy(&priv->statistics.tx, tx, sizeof(*tx)); -#ifdef CONFIG_IWLWIFI_DEBUGFS - if (bt_activity) - memcpy(&priv->statistics.bt_activity, bt_activity, - sizeof(*bt_activity)); -#endif - - priv->rx_statistics_jiffies = stamp; + iwl_recover_from_statistics(priv, pkt); set_bit(STATUS_STATISTICS, &priv->status); @@ -677,12 +708,18 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv, if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { #ifdef CONFIG_IWLWIFI_DEBUGFS - memset(&priv->accum_stats, 0, - sizeof(priv->accum_stats)); - memset(&priv->delta_stats, 0, - sizeof(priv->delta_stats)); - memset(&priv->max_delta_stats, 0, - sizeof(priv->max_delta_stats)); + memset(&priv->_agn.accum_statistics, 0, + sizeof(struct iwl_notif_statistics)); + memset(&priv->_agn.delta_statistics, 0, + sizeof(struct iwl_notif_statistics)); + memset(&priv->_agn.max_delta, 0, + sizeof(struct iwl_notif_statistics)); + memset(&priv->_agn.accum_statistics_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->_agn.delta_statistics_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->_agn.max_delta_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); #endif IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); } @@ -836,7 +873,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, { struct sk_buff *skb; __le16 fc = hdr->frame_control; - struct iwl_rxon_context *ctx; /* We only process data packets if the interface is open */ if (unlikely(!priv->is_open)) { @@ -859,29 +895,10 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); iwl_update_stats(priv, false, fc, len); - - /* - * Wake any queues that were stopped due to a passive channel tx - * failure. This can happen because the regulatory enforcement in - * the device waits for a beacon before allowing transmission, - * sometimes even after already having transmitted frames for the - * association because the new RXON may reset the information. - */ - if (unlikely(ieee80211_is_beacon(fc))) { - for_each_context(priv, ctx) { - if (!ctx->last_tx_rejected) - continue; - if (compare_ether_addr(hdr->addr3, - ctx->active.bssid_addr)) - continue; - ctx->last_tx_rejected = false; - iwl_wake_any_queue(priv, ctx); - } - } - memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(priv->hw, skb); + priv->alloc_rxb_page--; rxb->page = NULL; } @@ -1076,6 +1093,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) handlers = priv->rx_handlers; + handlers[REPLY_ALIVE] = iwl_rx_reply_alive; handlers[REPLY_ERROR] = iwl_rx_reply_error; handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c index c517f6d8a15f..3a4d9e6b0421 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h index cb80bb4ce45e..c4ca0b5d77da 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-spectrum.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ieee80211 subsystem header files. * diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c index 3c8cebde16cc..bc90a12408a3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -233,6 +233,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_station_entry *station; int i; u8 sta_id = IWL_INVALID_STATION; + u16 rate; if (is_ap) sta_id = ctx->ap_sta_id; @@ -305,6 +306,12 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, */ iwl_set_ht_add_station(priv, sta_id, sta, ctx); + /* 3945 only */ + rate = (priv->band == IEEE80211_BAND_5GHZ) ? + IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP; + /* Turn on both antennas for the station... */ + station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); + return sta_id; } @@ -494,8 +501,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, priv->num_stations--; - if (WARN_ON(priv->num_stations < 0)) - priv->num_stations = 0; + BUG_ON(priv->num_stations < 0); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -680,8 +686,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; priv->num_stations--; - if (WARN_ON(priv->num_stations < 0)) - priv->num_stations = 0; + BUG_ON(priv->num_stations < 0); kfree(priv->stations[i].lq); priv->stations[i].lq = NULL; } @@ -777,8 +782,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, spin_unlock_irqrestore(&priv->sta_lock, flags_spin); iwl_dump_lq_cmd(priv, lq); - if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) - return -EINVAL; + BUG_ON(init && (cmd.flags & CMD_ASYNC)); if (is_lq_table_valid(priv, ctx, lq)) ret = iwl_send_cmd(priv, &cmd); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h index ff64027ff4cb..206f1e1a0caf 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c index 52b1b66f32d0..277c9175dcf6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -149,31 +149,32 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; int i; + bool huge = false; if (q->n_bd == 0) return; while (q->read_ptr != q->write_ptr) { + /* we have no way to tell if it is a huge cmd ATM */ i = get_cmd_index(q, q->read_ptr, 0); - if (txq->meta[i].flags & CMD_MAPPED) { + if (txq->meta[i].flags & CMD_SIZE_HUGE) + huge = true; + else pci_unmap_single(priv->pci_dev, dma_unmap_addr(&txq->meta[i], mapping), dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); - txq->meta[i].flags = 0; - } - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } - i = q->n_window; - if (txq->meta[i].flags & CMD_MAPPED) { + if (huge) { + i = q->n_window; pci_unmap_single(priv->pci_dev, dma_unmap_addr(&txq->meta[i], mapping), dma_unmap_len(&txq->meta[i], len), PCI_DMA_BIDIRECTIONAL); - txq->meta[i].flags = 0; } } @@ -232,6 +233,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) * reclaiming packets (on 'tx done IRQ), if free space become > high mark, * Tx queue resumed. * + * See more detailed info in iwl-4965-hw.h. ***************************************************/ int iwl_queue_space(const struct iwl_queue *q) @@ -263,13 +265,11 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, /* count must be power-of-two size, otherwise iwl_queue_inc_wrap * and iwl_queue_dec_wrap are broken. */ - if (WARN_ON(!is_power_of_2(count))) - return -EINVAL; + BUG_ON(!is_power_of_2(count)); /* slots_num must be power-of-two size, otherwise * get_cmd_index is broken. */ - if (WARN_ON(!is_power_of_2(slots_num))) - return -EINVAL; + BUG_ON(!is_power_of_2(slots_num)); q->low_mark = q->n_window / 4; if (q->low_mark < 4) @@ -386,9 +386,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue's high/low-water marks, and head/tail indexes */ - ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); - if (ret) - return ret; + iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ priv->cfg->ops->lib->txq_init(priv, txq); @@ -450,19 +448,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); - /* - * If any of the command structures end up being larger than + /* If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then * we will need to increase the size of the TFD entries * Also, check to see if command buffer should not exceed the size - * of device_cmd and max_cmd_size. - */ - if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && - !(cmd->flags & CMD_SIZE_HUGE))) - return -EINVAL; - - if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE)) - return -EINVAL; + * of device_cmd and max_cmd_size. */ + BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && + !(cmd->flags & CMD_SIZE_HUGE)); + BUG_ON(fix_size > IWL_MAX_CMD_SIZE); if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", @@ -470,39 +463,35 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } - /* - * As we only have a single huge buffer, check that the command - * is synchronous (otherwise buffers could end up being reused). - */ - - if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE))) - return -EINVAL; - - spin_lock_irqsave(&priv->hcmd_lock, flags); - if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - spin_unlock_irqrestore(&priv->hcmd_lock, flags); - IWL_ERR(priv, "No space in command queue\n"); - is_ct_kill = iwl_check_for_ct_kill(priv); + if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { + is_ct_kill = + priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); + } if (!is_ct_kill) { IWL_ERR(priv, "Restarting adapter due to queue full\n"); - iwlagn_fw_error(priv, false); + queue_work(priv->workqueue, &priv->restart); } return -ENOSPC; } + spin_lock_irqsave(&priv->hcmd_lock, flags); + + /* If this is a huge cmd, mark the huge flag also on the meta.flags + * of the _original_ cmd. This is used for DMA mapping clean up. + */ + if (cmd->flags & CMD_SIZE_HUGE) { + idx = get_cmd_index(q, q->write_ptr, 0); + txq->meta[idx].flags = CMD_SIZE_HUGE; + } + idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); out_cmd = txq->cmd[idx]; out_meta = &txq->meta[idx]; - if (WARN_ON(out_meta->flags & CMD_MAPPED)) { - spin_unlock_irqrestore(&priv->hcmd_lock, flags); - return -ENOSPC; - } - memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ - out_meta->flags = cmd->flags | CMD_MAPPED; + out_meta->flags = cmd->flags; if (cmd->flags & CMD_WANT_SKB) out_meta->source = cmd; if (cmd->flags & CMD_ASYNC) @@ -595,7 +584,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, if (nfreed++ > 0) { IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, q->write_ptr, q->read_ptr); - iwlagn_fw_error(priv, false); + queue_work(priv->workqueue, &priv->restart); } } @@ -620,7 +609,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; - unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -634,6 +622,14 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) return; } + /* If this is a huge cmd, clear the huge flag on the meta.flags + * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap + * the DMA buffer for the scan (huge) command. + */ + if (huge) { + cmd_index = get_cmd_index(&txq->q, index, 0); + txq->meta[cmd_index].flags = 0; + } cmd_index = get_cmd_index(&txq->q, index, huge); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; @@ -650,8 +646,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } else if (meta->callback) meta->callback(priv, cmd, pkt); - spin_lock_irqsave(&priv->hcmd_lock, flags); - iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); if (!(meta->flags & CMD_ASYNC)) { @@ -660,9 +654,5 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } - - /* Mark as unmapped */ meta->flags = 0; - - spin_unlock_irqrestore(&priv->hcmd_lock, flags); } diff --git a/trunk/drivers/net/wireless/libertas/cfg.c b/trunk/drivers/net/wireless/libertas/cfg.c index f582dfd2927f..30ef0351bfc4 100644 --- a/trunk/drivers/net/wireless/libertas/cfg.c +++ b/trunk/drivers/net/wireless/libertas/cfg.c @@ -122,10 +122,8 @@ static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type) } -/* - * Various firmware commands need the list of supported rates, but with - * the hight-bit set for basic rates - */ +/* Various firmware commands need the list of supported rates, but with + the hight-bit set for basic rates */ static int lbs_add_rates(u8 *rates) { size_t i; @@ -427,7 +425,7 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) return ie_len + 2; } -/* +/*************************************************************************** * Set Channel */ @@ -454,7 +452,7 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy, -/* +/*************************************************************************** * Scanning */ @@ -540,10 +538,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, goto done; } - /* - * Validity check: the TLV holds TSF values with 8 bytes each, so - * the size in the TLV must match the nr_sets value - */ + /* Validity check: the TLV holds TSF values with 8 bytes each, so + * the size in the TLV must match the nr_sets value */ i = get_unaligned_le16(tsfdesc); tsfdesc += 2; if (i / 8 != scanresp->nr_sets) { @@ -585,10 +581,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, /* To find out the channel, we must parse the IEs */ ie = pos; - /* - * 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon - * interval, capabilities - */ + /* 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon + interval, capabilities */ ielen = left = len - (6 + 1 + 8 + 2 + 2); while (left >= 2) { u8 id, elen; @@ -796,7 +790,7 @@ static int lbs_cfg_scan(struct wiphy *wiphy, -/* +/*************************************************************************** * Events */ @@ -831,7 +825,7 @@ void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event) -/* +/*************************************************************************** * Connect/disconnect */ @@ -956,10 +950,8 @@ static int lbs_enable_rsn(struct lbs_private *priv, int enable) * Set WPA/WPA key material */ -/* - * like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we - * get rid of WEXT, this should go into host.h - */ +/* like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we + * get rid of WEXT, this should go into host.h */ struct cmd_key_material { struct cmd_header hdr; @@ -1544,7 +1536,7 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, } -/* +/*************************************************************************** * Get station */ @@ -1589,7 +1581,7 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, -/* +/*************************************************************************** * "Site survey", here just current channel and noise level */ @@ -1622,7 +1614,7 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev, -/* +/*************************************************************************** * Change interface */ @@ -1664,12 +1656,11 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, -/* +/*************************************************************************** * IBSS (Ad-Hoc) */ -/* - * The firmware needs the following bits masked out of the beacon-derived +/* The firmware needs the following bits masked out of the beacon-derived * capability field when associating/joining to a BSS: * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) */ @@ -2008,7 +1999,7 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -/* +/*************************************************************************** * Initialization */ diff --git a/trunk/drivers/net/wireless/libertas/cmd.c b/trunk/drivers/net/wireless/libertas/cmd.c index 6a96fc9c1cea..7e8a658b7670 100644 --- a/trunk/drivers/net/wireless/libertas/cmd.c +++ b/trunk/drivers/net/wireless/libertas/cmd.c @@ -1,7 +1,7 @@ -/* - * This file contains the handling of command. - * It prepares command and sends it to firmware when it is ready. - */ +/** + * This file contains the handling of command. + * It prepares command and sends it to firmware when it is ready. + */ #include #include @@ -16,14 +16,14 @@ #define CAL_RSSI(snr, nf) ((s32)((s32)(snr) + CAL_NF(nf))) /** - * lbs_cmd_copyback - Simple callback that copies response back into command + * @brief Simple callback that copies response back into command * - * @priv: A pointer to &struct lbs_private structure - * @extra: A pointer to the original command structure for which - * 'resp' is a response - * @resp: A pointer to the command response + * @param priv A pointer to struct lbs_private structure + * @param extra A pointer to the original command structure for which + * 'resp' is a response + * @param resp A pointer to the command response * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp) @@ -38,15 +38,15 @@ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, EXPORT_SYMBOL_GPL(lbs_cmd_copyback); /** - * lbs_cmd_async_callback - Simple callback that ignores the result. - * Use this if you just want to send a command to the hardware, but don't + * @brief Simple callback that ignores the result. Use this if + * you just want to send a command to the hardware, but don't * care for the result. * - * @priv: ignored - * @extra: ignored - * @resp: ignored + * @param priv ignored + * @param extra ignored + * @param resp ignored * - * returns: 0 for success + * @return 0 for success */ static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp) @@ -56,11 +56,10 @@ static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, /** - * is_command_allowed_in_ps - tests if a command is allowed in Power Save mode - * - * @cmd: the command ID + * @brief Checks whether a command is allowed in Power Save mode * - * returns: 1 if allowed, 0 if not allowed + * @param command the command ID + * @return 1 if allowed, 0 if not allowed */ static u8 is_command_allowed_in_ps(u16 cmd) { @@ -76,12 +75,11 @@ static u8 is_command_allowed_in_ps(u16 cmd) } /** - * lbs_update_hw_spec - Updates the hardware details like MAC address - * and regulatory region + * @brief Updates the hardware details like MAC address and regulatory region * - * @priv: A pointer to &struct lbs_private structure + * @param priv A pointer to struct lbs_private structure * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_update_hw_spec(struct lbs_private *priv) { @@ -219,14 +217,14 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); /** - * lbs_set_ps_mode - Sets the Power Save mode + * @brief Sets the Power Save mode * - * @priv: A pointer to &struct lbs_private structure - * @cmd_action: The Power Save operation (PS_MODE_ACTION_ENTER_PS or + * @param priv A pointer to struct lbs_private structure + * @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or * PS_MODE_ACTION_EXIT_PS) - * @block: Whether to block on a response or not + * @param block Whether to block on a response or not * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block) { @@ -419,13 +417,13 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) } /** - * lbs_set_snmp_mib - Set an SNMP MIB value + * @brief Set an SNMP MIB value * - * @priv: A pointer to &struct lbs_private structure - * @oid: The OID to set in the firmware - * @val: Value to set the OID to + * @param priv A pointer to struct lbs_private structure + * @param oid The OID to set in the firmware + * @param val Value to set the OID to * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) { @@ -469,13 +467,13 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) } /** - * lbs_get_snmp_mib - Get an SNMP MIB value + * @brief Get an SNMP MIB value * - * @priv: A pointer to &struct lbs_private structure - * @oid: The OID to retrieve from the firmware - * @out_val: Location for the returned value + * @param priv A pointer to struct lbs_private structure + * @param oid The OID to retrieve from the firmware + * @param out_val Location for the returned value * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) { @@ -512,14 +510,14 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) } /** - * lbs_get_tx_power - Get the min, max, and current TX power + * @brief Get the min, max, and current TX power * - * @priv: A pointer to &struct lbs_private structure - * @curlevel: Current power level in dBm - * @minlevel: Minimum supported power level in dBm (optional) - * @maxlevel: Maximum supported power level in dBm (optional) + * @param priv A pointer to struct lbs_private structure + * @param curlevel Current power level in dBm + * @param minlevel Minimum supported power level in dBm (optional) + * @param maxlevel Maximum supported power level in dBm (optional) * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, s16 *maxlevel) @@ -547,12 +545,12 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, } /** - * lbs_set_tx_power - Set the TX power + * @brief Set the TX power * - * @priv: A pointer to &struct lbs_private structure - * @dbm: The desired power level in dBm + * @param priv A pointer to struct lbs_private structure + * @param dbm The desired power level in dBm * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) { @@ -575,13 +573,12 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) } /** - * lbs_set_monitor_mode - Enable or disable monitor mode - * (only implemented on OLPC usb8388 FW) + * @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW) * - * @priv: A pointer to &struct lbs_private structure - * @enable: 1 to enable monitor mode, 0 to disable + * @param priv A pointer to struct lbs_private structure + * @param enable 1 to enable monitor mode, 0 to disable * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_set_monitor_mode(struct lbs_private *priv, int enable) { @@ -607,11 +604,11 @@ int lbs_set_monitor_mode(struct lbs_private *priv, int enable) } /** - * lbs_get_channel - Get the radio channel + * @brief Get the radio channel * - * @priv: A pointer to &struct lbs_private structure + * @param priv A pointer to struct lbs_private structure * - * returns: The channel on success, error on failure + * @return The channel on success, error on failure */ static int lbs_get_channel(struct lbs_private *priv) { @@ -653,12 +650,12 @@ int lbs_update_channel(struct lbs_private *priv) } /** - * lbs_set_channel - Set the radio channel + * @brief Set the radio channel * - * @priv: A pointer to &struct lbs_private structure - * @channel: The desired channel, or 0 to clear a locked channel + * @param priv A pointer to struct lbs_private structure + * @param channel The desired channel, or 0 to clear a locked channel * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_set_channel(struct lbs_private *priv, u8 channel) { @@ -689,13 +686,12 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) } /** - * lbs_get_rssi - Get current RSSI and noise floor + * @brief Get current RSSI and noise floor * - * @priv: A pointer to &struct lbs_private structure - * @rssi: On successful return, signal level in mBm - * @nf: On successful return, Noise floor + * @param priv A pointer to struct lbs_private structure + * @param rssi On successful return, signal level in mBm * - * returns: The channel on success, error on failure + * @return The channel on success, error on failure */ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) { @@ -723,14 +719,13 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) } /** - * lbs_set_11d_domain_info - Send regulatory and 802.11d domain information - * to the firmware + * @brief Send regulatory and 802.11d domain information to the firmware * - * @priv: pointer to &struct lbs_private - * @request: cfg80211 regulatory request structure - * @bands: the device's supported bands and channels + * @param priv pointer to struct lbs_private + * @param request cfg80211 regulatory request structure + * @param bands the device's supported bands and channels * - * returns: 0 on success, error code on failure + * @return 0 on success, error code on failure */ int lbs_set_11d_domain_info(struct lbs_private *priv, struct regulatory_request *request, @@ -847,15 +842,15 @@ int lbs_set_11d_domain_info(struct lbs_private *priv, } /** - * lbs_get_reg - Read a MAC, Baseband, or RF register + * @brief Read a MAC, Baseband, or RF register * - * @priv: pointer to &struct lbs_private - * @reg: register command, one of CMD_MAC_REG_ACCESS, - * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS - * @offset: byte offset of the register to get - * @value: on success, the value of the register at 'offset' + * @param priv pointer to struct lbs_private + * @param cmd register command, one of CMD_MAC_REG_ACCESS, + * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + * @param offset byte offset of the register to get + * @param value on success, the value of the register at 'offset' * - * returns: 0 on success, error code on failure + * @return 0 on success, error code on failure */ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value) { @@ -891,15 +886,15 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value) } /** - * lbs_set_reg - Write a MAC, Baseband, or RF register + * @brief Write a MAC, Baseband, or RF register * - * @priv: pointer to &struct lbs_private - * @reg: register command, one of CMD_MAC_REG_ACCESS, - * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS - * @offset: byte offset of the register to set - * @value: the value to write to the register at 'offset' + * @param priv pointer to struct lbs_private + * @param cmd register command, one of CMD_MAC_REG_ACCESS, + * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS + * @param offset byte offset of the register to set + * @param value the value to write to the register at 'offset' * - * returns: 0 on success, error code on failure + * @return 0 on success, error code on failure */ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value) { @@ -1028,7 +1023,7 @@ static void lbs_submit_command(struct lbs_private *priv, lbs_deb_leave(LBS_DEB_HOST); } -/* +/** * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held. */ @@ -1130,12 +1125,11 @@ void lbs_set_mac_control(struct lbs_private *priv) } /** - * lbs_allocate_cmd_buffer - allocates the command buffer and links - * it to command free queue - * - * @priv: A pointer to &struct lbs_private structure + * @brief This function allocates the command buffer and link + * it to command free queue. * - * returns: 0 for success or -1 on error + * @param priv A pointer to struct lbs_private structure + * @return 0 or -1 */ int lbs_allocate_cmd_buffer(struct lbs_private *priv) { @@ -1177,11 +1171,10 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv) } /** - * lbs_free_cmd_buffer - free the command buffer + * @brief This function frees the command buffer. * - * @priv: A pointer to &struct lbs_private structure - * - * returns: 0 for success + * @param priv A pointer to struct lbs_private structure + * @return 0 or -1 */ int lbs_free_cmd_buffer(struct lbs_private *priv) { @@ -1218,13 +1211,11 @@ int lbs_free_cmd_buffer(struct lbs_private *priv) } /** - * lbs_get_free_cmd_node - gets a free command node if available in - * command free queue - * - * @priv: A pointer to &struct lbs_private structure + * @brief This function gets a free command node if available in + * command free queue. * - * returns: A pointer to &cmd_ctrl_node structure on success - * or %NULL on error + * @param priv A pointer to struct lbs_private structure + * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL */ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv) { @@ -1254,12 +1245,12 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv) } /** - * lbs_execute_next_command - execute next command in command - * pending queue. Will put firmware back to PS mode if applicable. + * @brief This function executes next command in command + * pending queue. It will put firmware back to PS mode + * if applicable. * - * @priv: A pointer to &struct lbs_private structure - * - * returns: 0 on success or -1 on error + * @param priv A pointer to struct lbs_private structure + * @return 0 or -1 */ int lbs_execute_next_command(struct lbs_private *priv) { @@ -1463,12 +1454,12 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) } /** - * lbs_ps_confirm_sleep - checks condition and prepares to - * send sleep confirm command to firmware if ok - * - * @priv: A pointer to &struct lbs_private structure + * @brief This function checks condition and prepares to + * send sleep confirm command to firmware if ok. * - * returns: n/a + * @param priv A pointer to struct lbs_private structure + * @param psmode Power Saving mode + * @return n/a */ void lbs_ps_confirm_sleep(struct lbs_private *priv) { @@ -1508,16 +1499,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) /** - * lbs_set_tpc_cfg - Configures the transmission power control functionality + * @brief Configures the transmission power control functionality. * - * @priv: A pointer to &struct lbs_private structure - * @enable: Transmission power control enable - * @p0: Power level when link quality is good (dBm). - * @p1: Power level when link quality is fair (dBm). - * @p2: Power level when link quality is poor (dBm). - * @usesnr: Use Signal to Noise Ratio in TPC + * @param priv A pointer to struct lbs_private structure + * @param enable Transmission power control enable + * @param p0 Power level when link quality is good (dBm). + * @param p1 Power level when link quality is fair (dBm). + * @param p2 Power level when link quality is poor (dBm). + * @param usesnr Use Signal to Noise Ratio in TPC * - * returns: 0 on success + * @return 0 on success */ int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, int8_t p2, int usesnr) @@ -1540,15 +1531,15 @@ int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, } /** - * lbs_set_power_adapt_cfg - Configures the power adaptation settings + * @brief Configures the power adaptation settings. * - * @priv: A pointer to &struct lbs_private structure - * @enable: Power adaptation enable - * @p0: Power level for 1, 2, 5.5 and 11 Mbps (dBm). - * @p1: Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). - * @p2: Power level for 48 and 54 Mbps (dBm). + * @param priv A pointer to struct lbs_private structure + * @param enable Power adaptation enable + * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm). + * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). + * @param p2 Power level for 48 and 54 Mbps (dBm). * - * returns: 0 on Success + * @return 0 on Success */ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, diff --git a/trunk/drivers/net/wireless/libertas/cmdresp.c b/trunk/drivers/net/wireless/libertas/cmdresp.c index 03e528994a9e..5e95da9dcc2e 100644 --- a/trunk/drivers/net/wireless/libertas/cmdresp.c +++ b/trunk/drivers/net/wireless/libertas/cmdresp.c @@ -1,7 +1,7 @@ -/* - * This file contains the handling of command - * responses as well as events generated by firmware. - */ +/** + * This file contains the handling of command + * responses as well as events generated by firmware. + */ #include #include #include @@ -12,13 +12,12 @@ #include "cmd.h" /** - * lbs_mac_event_disconnected - handles disconnect event. It - * reports disconnect to upper layer, clean tx/rx packets, - * reset link state etc. - * - * @priv: A pointer to struct lbs_private structure + * @brief This function handles disconnect event. it + * reports disconnect to upper layer, clean tx/rx packets, + * reset link state etc. * - * returns: n/a + * @param priv A pointer to struct lbs_private structure + * @return n/a */ void lbs_mac_event_disconnected(struct lbs_private *priv) { diff --git a/trunk/drivers/net/wireless/libertas/debugfs.c b/trunk/drivers/net/wireless/libertas/debugfs.c index 851fe7bd4ba4..fbf3b0332bb7 100644 --- a/trunk/drivers/net/wireless/libertas/debugfs.c +++ b/trunk/drivers/net/wireless/libertas/debugfs.c @@ -849,14 +849,15 @@ static struct debug_data items[] = { static int num_of_items = ARRAY_SIZE(items); /** - * lbs_debugfs_read - proc read function + * @brief proc read function * - * @file: file to read - * @userbuf: pointer to buffer - * @count: number of bytes to read - * @ppos: read data starting position - * - * returns: amount of data read or negative error code + * @param page pointer to buffer + * @param s read data starting position + * @param off offset + * @param cnt counter + * @param eof end of file flag + * @param data data to output + * @return number of output data */ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) @@ -896,14 +897,13 @@ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, } /** - * lbs_debugfs_write - proc write function - * - * @f: file pointer - * @buf: pointer to data buffer - * @cnt: data number to write - * @ppos: file position + * @brief proc write function * - * returns: amount of data written + * @param f file pointer + * @param buf pointer to data buffer + * @param cnt data number to write + * @param data data to write + * @return number of data */ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, size_t cnt, loff_t *ppos) @@ -966,11 +966,11 @@ static const struct file_operations lbs_debug_fops = { }; /** - * lbs_debug_init - create debug proc file - * - * @priv: pointer to &struct lbs_private + * @brief create debug proc file * - * returns: N/A + * @param priv pointer struct lbs_private + * @param dev pointer net_device + * @return N/A */ static void lbs_debug_init(struct lbs_private *priv) { diff --git a/trunk/drivers/net/wireless/libertas/decl.h b/trunk/drivers/net/wireless/libertas/decl.h index da0b05bb89fe..2ae752d10065 100644 --- a/trunk/drivers/net/wireless/libertas/decl.h +++ b/trunk/drivers/net/wireless/libertas/decl.h @@ -1,8 +1,8 @@ -/* - * This file contains declaration referring to - * functions defined in other source files - */ +/** + * This file contains declaration referring to + * functions defined in other source files + */ #ifndef _LBS_DECL_H_ #define _LBS_DECL_H_ diff --git a/trunk/drivers/net/wireless/libertas/defs.h b/trunk/drivers/net/wireless/libertas/defs.h index 92b5b1f8fd75..d00c728cec47 100644 --- a/trunk/drivers/net/wireless/libertas/defs.h +++ b/trunk/drivers/net/wireless/libertas/defs.h @@ -1,7 +1,7 @@ -/* - * This header file contains global constant/enum definitions, - * global variable declaration. - */ +/** + * This header file contains global constant/enum definitions, + * global variable declaration. + */ #ifndef _LBS_DEFS_H_ #define _LBS_DEFS_H_ @@ -123,19 +123,19 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in -/* Buffer Constants */ +/** Buffer Constants */ /* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical - * addresses of TxPD buffers. Station has only 8 TxPD available, Whereas - * driver has more local TxPDs. Each TxPD on the host memory is associated - * with a Tx control node. The driver maintains 8 RxPD descriptors for - * station firmware to store Rx packet information. - * - * Current version of MAC has a 32x6 multicast address buffer. - * - * 802.11b can have up to 14 channels, the driver keeps the - * BSSID(MAC address) of each APs or Ad hoc stations it has sensed. - */ +* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas +* driver has more local TxPDs. Each TxPD on the host memory is associated +* with a Tx control node. The driver maintains 8 RxPD descriptors for +* station firmware to store Rx packet information. +* +* Current version of MAC has a 32x6 multicast address buffer. +* +* 802.11b can have up to 14 channels, the driver keeps the +* BSSID(MAC address) of each APs or Ad hoc stations it has sensed. +*/ #define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 #define LBS_NUM_CMD_BUFFERS 10 @@ -166,7 +166,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define WOL_RESULT_NOSPC_ERR 1 #define WOL_RESULT_EEXIST_ERR 2 -/* Misc constants */ +/** Misc constants */ /* This section defines 802.11 specific contants */ #define MRVDRV_MAX_BSS_DESCRIPTS 16 @@ -183,8 +183,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MARVELL_MESH_IE_LENGTH 9 -/* - * Values used to populate the struct mrvl_mesh_ie. The only time you need this +/* Values used to populate the struct mrvl_mesh_ie. The only time you need this * is when enabling the mesh using CMD_MESH_CONFIG. */ #define MARVELL_MESH_IE_TYPE 4 @@ -194,7 +193,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MARVELL_MESH_METRIC_ID 0 #define MARVELL_MESH_CAPABILITY 0 -/* INT status Bit Definition */ +/** INT status Bit Definition*/ #define MRVDRV_TX_DNLD_RDY 0x0001 #define MRVDRV_RX_UPLD_RDY 0x0002 #define MRVDRV_CMD_DNLD_RDY 0x0004 @@ -209,63 +208,59 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define TPC_DEFAULT_P1 10 #define TPC_DEFAULT_P2 13 -/* TxPD status */ +/** TxPD status */ -/* - * Station firmware use TxPD status field to report final Tx transmit - * result, Bit masks are used to present combined situations. - */ +/* Station firmware use TxPD status field to report final Tx transmit +* result, Bit masks are used to present combined situations. +*/ #define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01 #define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08 -/* Tx mesh flag */ -/* - * Currently we are using normal WDS flag as mesh flag. +/** Tx mesh flag */ +/* Currently we are using normal WDS flag as mesh flag. * TODO: change to proper mesh flag when MAC understands it. */ #define TxPD_CONTROL_WDS_FRAME (1<<17) #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME -/* Mesh interface ID */ +/** Mesh interface ID */ #define MESH_IFACE_ID 0x0001 -/* Mesh id should be in bits 14-13-12 */ +/** Mesh id should be in bits 14-13-12 */ #define MESH_IFACE_BIT_OFFSET 0x000c -/* Mesh enable bit in FW capability */ +/** Mesh enable bit in FW capability */ #define MESH_CAPINFO_ENABLE_MASK (1<<16) -/* FW definition from Marvell v4 */ +/** FW definition from Marvell v4 */ #define MRVL_FW_V4 (0x04) -/* FW definition from Marvell v5 */ +/** FW definition from Marvell v5 */ #define MRVL_FW_V5 (0x05) -/* FW definition from Marvell v10 */ +/** FW definition from Marvell v10 */ #define MRVL_FW_V10 (0x0a) -/* FW major revision definition */ +/** FW major revision definition */ #define MRVL_FW_MAJOR_REV(x) ((x)>>24) -/* RxPD status */ +/** RxPD status */ #define MRVDRV_RXPD_STATUS_OK 0x0001 -/* RxPD status - Received packet types */ -/* Rx mesh flag */ -/* - * Currently we are using normal WDS flag as mesh flag. +/** RxPD status - Received packet types */ +/** Rx mesh flag */ +/* Currently we are using normal WDS flag as mesh flag. * TODO: change to proper mesh flag when MAC understands it. */ #define RxPD_CONTROL_WDS_FRAME (0x40) #define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME -/* RSSI-related defines */ -/* - * RSSI constants are used to implement 802.11 RSSI threshold - * indication. if the Rx packet signal got too weak for 5 consecutive - * times, miniport driver (driver) will report this event to wrapper - */ +/** RSSI-related defines */ +/* RSSI constants are used to implement 802.11 RSSI threshold +* indication. if the Rx packet signal got too weak for 5 consecutive +* times, miniport driver (driver) will report this event to wrapper +*/ #define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96) -/* RTS/FRAG related defines */ +/** RTS/FRAG related defines */ #define MRVDRV_RTS_MIN_VALUE 0 #define MRVDRV_RTS_MAX_VALUE 2347 #define MRVDRV_FRAG_MIN_VALUE 256 @@ -305,36 +300,36 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MAX_LEDS 8 -/* Global Variable Declaration */ +/** Global Variable Declaration */ extern const char lbs_driver_version[]; extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; -/* ENUM definition */ -/* SNRNF_TYPE */ +/** ENUM definition*/ +/** SNRNF_TYPE */ enum SNRNF_TYPE { TYPE_BEACON = 0, TYPE_RXPD, MAX_TYPE_B }; -/* SNRNF_DATA */ +/** SNRNF_DATA*/ enum SNRNF_DATA { TYPE_NOAVG = 0, TYPE_AVG, MAX_TYPE_AVG }; -/* LBS_802_11_POWER_MODE */ +/** LBS_802_11_POWER_MODE */ enum LBS_802_11_POWER_MODE { LBS802_11POWERMODECAM, LBS802_11POWERMODEMAX_PSP, LBS802_11POWERMODEFAST_PSP, - /* not a real mode, defined as an upper bound */ + /*not a real mode, defined as an upper bound */ LBS802_11POWEMODEMAX }; -/* PS_STATE */ +/** PS_STATE */ enum PS_STATE { PS_STATE_FULL_POWER, PS_STATE_AWAKE, @@ -342,7 +337,7 @@ enum PS_STATE { PS_STATE_SLEEP }; -/* DNLD_STATE */ +/** DNLD_STATE */ enum DNLD_STATE { DNLD_RES_RECEIVED, DNLD_DATA_SENT, @@ -350,19 +345,19 @@ enum DNLD_STATE { DNLD_BOOTCMD_SENT, }; -/* LBS_MEDIA_STATE */ +/** LBS_MEDIA_STATE */ enum LBS_MEDIA_STATE { LBS_CONNECTED, LBS_DISCONNECTED }; -/* LBS_802_11_PRIVACY_FILTER */ +/** LBS_802_11_PRIVACY_FILTER */ enum LBS_802_11_PRIVACY_FILTER { LBS802_11PRIVFILTERACCEPTALL, LBS802_11PRIVFILTER8021XWEP }; -/* mv_ms_type */ +/** mv_ms_type */ enum mv_ms_type { MVMS_DAT = 0, MVMS_CMD = 1, @@ -370,14 +365,14 @@ enum mv_ms_type { MVMS_EVENT }; -/* KEY_TYPE_ID */ +/** KEY_TYPE_ID */ enum KEY_TYPE_ID { KEY_TYPE_ID_WEP = 0, KEY_TYPE_ID_TKIP, KEY_TYPE_ID_AES }; -/* KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ +/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ enum KEY_INFO_WPA { KEY_INFO_WPA_MCAST = 0x01, KEY_INFO_WPA_UNICAST = 0x02, diff --git a/trunk/drivers/net/wireless/libertas/dev.h b/trunk/drivers/net/wireless/libertas/dev.h index 76d018beebf4..bc461eb39660 100644 --- a/trunk/drivers/net/wireless/libertas/dev.h +++ b/trunk/drivers/net/wireless/libertas/dev.h @@ -1,8 +1,8 @@ -/* - * This file contains definitions and data structures specific - * to Marvell 802.11 NIC. It contains the Device Information - * structure struct lbs_private.. - */ +/** + * This file contains definitions and data structures specific + * to Marvell 802.11 NIC. It contains the Device Information + * structure struct lbs_private.. + */ #ifndef _LBS_DEV_H_ #define _LBS_DEV_H_ @@ -12,7 +12,7 @@ #include -/* sleep_params */ +/** sleep_params */ struct sleep_params { uint16_t sp_error; uint16_t sp_offset; @@ -23,7 +23,7 @@ struct sleep_params { }; -/* Private structure for the MV device */ +/** Private structure for the MV device */ struct lbs_private { /* Basic networking */ @@ -125,12 +125,12 @@ struct lbs_private { /* Events sent from hardware to driver */ struct kfifo event_fifo; - /* thread to service interrupts */ + /** thread to service interrupts */ struct task_struct *main_thread; wait_queue_head_t waitq; struct workqueue_struct *work_thread; - /* Encryption stuff */ + /** Encryption stuff */ u8 authtype_auto; u8 wep_tx_key; u8 wep_key[4][WLAN_KEY_LEN_WEP104]; @@ -162,7 +162,7 @@ struct lbs_private { s16 txpower_min; s16 txpower_max; - /* Scanning */ + /** Scanning */ struct delayed_work scan_work; int scan_channel; /* Queue of things waiting for scan completion */ diff --git a/trunk/drivers/net/wireless/libertas/ethtool.c b/trunk/drivers/net/wireless/libertas/ethtool.c index 29dbce4a9f86..50193aac679e 100644 --- a/trunk/drivers/net/wireless/libertas/ethtool.c +++ b/trunk/drivers/net/wireless/libertas/ethtool.c @@ -20,8 +20,7 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev, strcpy(info->version, lbs_driver_version); } -/* - * All 8388 parts have 16KiB EEPROM size at the time of writing. +/* All 8388 parts have 16KiB EEPROM size at the time of writing. * In case that changes this needs fixing. */ #define LBS_EEPROM_LEN 16384 diff --git a/trunk/drivers/net/wireless/libertas/host.h b/trunk/drivers/net/wireless/libertas/host.h index 2e2dbfa2ee50..6cb6935ee4a3 100644 --- a/trunk/drivers/net/wireless/libertas/host.h +++ b/trunk/drivers/net/wireless/libertas/host.h @@ -1,7 +1,7 @@ -/* - * This file function prototypes, data structure - * and definitions for all the host/station commands - */ +/** + * This file function prototypes, data structure + * and definitions for all the host/station commands + */ #ifndef _LBS_HOST_H_ #define _LBS_HOST_H_ @@ -13,10 +13,9 @@ #define CMD_OPTION_WAITFORRSP 0x0002 -/* Host command IDs */ +/** Host command IDs */ -/* - * Return command are almost always the same as the host command, but with +/* Return command are almost always the same as the host command, but with * bit 15 set high. There are a few exceptions, though... */ #define CMD_RET(cmd) (0x8000 | cmd) @@ -252,7 +251,7 @@ enum cmd_mesh_config_types { CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */ }; -/* Card Event definition */ +/** Card Event definition */ #define MACREG_INT_CODE_TX_PPA_FREE 0 #define MACREG_INT_CODE_TX_DMA_DONE 1 #define MACREG_INT_CODE_LINK_LOST_W_SCAN 2 @@ -625,14 +624,12 @@ struct cmd_ds_802_11_rf_channel { struct cmd_ds_802_11_rssi { struct cmd_header hdr; - /* - * request: number of beacons (N) to average the SNR and NF over + /* request: number of beacons (N) to average the SNR and NF over * response: SNR of most recent beacon */ __le16 n_or_snr; - /* - * The following fields are only set in the response. + /* The following fields are only set in the response. * In the request these are reserved and should be set to 0. */ __le16 nf; /* most recent beacon noise floor */ @@ -683,16 +680,14 @@ struct cmd_ds_802_11_ps_mode { __le16 action; - /* - * Interval for keepalive in PS mode: + /* Interval for keepalive in PS mode: * 0x0000 = don't change * 0x001E = firmware default * 0xFFFF = disable */ __le16 nullpktinterval; - /* - * Number of DTIM intervals to wake up for: + /* Number of DTIM intervals to wake up for: * 0 = don't change * 1 = firmware default * 5 = max @@ -702,8 +697,7 @@ struct cmd_ds_802_11_ps_mode { __le16 reserved; __le16 locallisteninterval; - /* - * AdHoc awake period (FW v9+ only): + /* AdHoc awake period (FW v9+ only): * 0 = don't change * 1 = always awake (IEEE standard behavior) * 2 - 31 = sleep for (n - 1) periods and awake for 1 period @@ -777,8 +771,7 @@ struct adhoc_bssdesc { __le16 capability; u8 rates[MAX_RATES]; - /* - * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the + /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the * Adhoc join command and will cause a binary layout mismatch with * the firmware */ diff --git a/trunk/drivers/net/wireless/libertas/if_cs.c b/trunk/drivers/net/wireless/libertas/if_cs.c index 4dfd48fe8b6e..fc8121190d38 100644 --- a/trunk/drivers/net/wireless/libertas/if_cs.c +++ b/trunk/drivers/net/wireless/libertas/if_cs.c @@ -312,8 +312,7 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define CF8385_MANFID 0x02df #define CF8385_CARDID 0x8103 -/* - * FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when +/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when * that gets fixed. Currently there's no way to access it from the probe hook. */ static inline u32 get_model(u16 manf_id, u16 card_id) @@ -622,10 +621,8 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) if (remain < count) count = remain; - /* - * "write the number of bytes to be sent to the I/O Command - * write length register" - */ + /* "write the number of bytes to be sent to the I/O Command + * write length register" */ if_cs_write16(card, IF_CS_CMD_LEN, count); /* "write this to I/O Command port register as 16 bit writes */ @@ -634,22 +631,16 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) &fw->data[sent], count >> 1); - /* - * "Assert the download over interrupt command in the Host - * status register" - */ + /* "Assert the download over interrupt command in the Host + * status register" */ if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); - /* - * "Assert the download over interrupt command in the Card - * interrupt case register" - */ + /* "Assert the download over interrupt command in the Card + * interrupt case register" */ if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); - /* - * "The host polls the Card Status register ... for 50 ms before - * declaring a failure" - */ + /* "The host polls the Card Status register ... for 50 ms before + declaring a failure */ ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, IF_CS_BIT_COMMAND); if (ret < 0) { @@ -850,7 +841,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) /* * Most of the libertas cards can do unaligned register access, but some - * weird ones cannot. That's especially true for the CF8305 card. + * weird ones can not. That's especially true for the CF8305 card. */ card->align_regs = 0; @@ -922,10 +913,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out3; } - /* - * Clear any interrupt cause that happened while sending - * firmware/initializing card - */ + /* Clear any interrupt cause that happend while sending + * firmware/initializing card */ if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); if_cs_enable_ints(card); diff --git a/trunk/drivers/net/wireless/libertas/if_spi.c b/trunk/drivers/net/wireless/libertas/if_spi.c index 67de5b3c68b2..f6c2cd665f49 100644 --- a/trunk/drivers/net/wireless/libertas/if_spi.c +++ b/trunk/drivers/net/wireless/libertas/if_spi.c @@ -57,7 +57,6 @@ struct if_spi_card { /* Handles all SPI communication (except for FW load) */ struct workqueue_struct *workqueue; struct work_struct packet_work; - struct work_struct resume_work; u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; @@ -69,9 +68,6 @@ struct if_spi_card { /* Protects cmd_packet_list and data_packet_list */ spinlock_t buffer_lock; - - /* True is card suspended */ - u8 suspended; }; static void free_if_spi_card(struct if_spi_card *card) @@ -143,10 +139,8 @@ static void spu_transaction_finish(struct if_spi_card *card) card->prev_xfer_time = jiffies; } -/* - * Write out a byte buffer to an SPI register, - * using a series of 16-bit transfers. - */ +/* Write out a byte buffer to an SPI register, + * using a series of 16-bit transfers. */ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) { int err = 0; @@ -210,10 +204,8 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) struct spi_transfer dummy_trans; struct spi_transfer data_trans; - /* - * You must take an even number of bytes from the SPU, even if you - * don't care about the last one. - */ + /* You must take an even number of bytes from the SPU, even if you + * don't care about the last one. */ BUG_ON(len & 0x1); spu_transaction_init(card); @@ -262,10 +254,8 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) return ret; } -/* - * Read 32 bits from an SPI register. - * The low 16 bits are read first. - */ +/* Read 32 bits from an SPI register. + * The low 16 bits are read first. */ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) { __le32 buf; @@ -277,15 +267,13 @@ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) return err; } -/* - * Keep reading 16 bits from an SPI register until you get the correct result. +/* Keep reading 16 bits from an SPI register until you get the correct result. * * If mask = 0, the correct result is any non-zero number. * If mask != 0, the correct result is any number where * number & target_mask == target * - * Returns -ETIMEDOUT if a second passes without the correct result. - */ + * Returns -ETIMEDOUT if a second passes without the correct result. */ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, u16 target_mask, u16 target) { @@ -313,10 +301,8 @@ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, } } -/* - * Read 16 bits from an SPI register until you receive a specific value. - * Returns -ETIMEDOUT if a 4 tries pass without success. - */ +/* Read 16 bits from an SPI register until you receive a specific value. + * Returns -ETIMEDOUT if a 4 tries pass without success. */ static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target) { int err, try; @@ -338,10 +324,8 @@ static int spu_set_interrupt_mode(struct if_spi_card *card, { int err = 0; - /* - * We can suppress a host interrupt by clearing the appropriate - * bit in the "host interrupt status mask" register - */ + /* We can suppress a host interrupt by clearing the appropriate + * bit in the "host interrupt status mask" register */ if (suppress_host_int) { err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); if (err) @@ -357,12 +341,10 @@ static int spu_set_interrupt_mode(struct if_spi_card *card, return err; } - /* - * If auto-interrupts are on, the completion of certain transactions + /* If auto-interrupts are on, the completion of certain transactions * will trigger an interrupt automatically. If auto-interrupts * are off, we need to set the "Card Interrupt Cause" register to - * trigger a card interrupt. - */ + * trigger a card interrupt. */ if (auto_int) { err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | @@ -416,10 +398,8 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) int err = 0; u32 delay; - /* - * We have to start up in timed delay mode so that we can safely - * read the Delay Read Register. - */ + /* We have to start up in timed delay mode so that we can safely + * read the Delay Read Register. */ card->use_dummy_writes = 0; err = spu_set_bus_mode(card, IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | @@ -475,10 +455,8 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, /* Load helper firmware image */ while (bytes_remaining > 0) { - /* - * Scratch pad 1 should contain the number of bytes we - * want to download to the firmware - */ + /* Scratch pad 1 should contain the number of bytes we + * want to download to the firmware */ err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, HELPER_FW_LOAD_CHUNK_SZ); if (err) @@ -490,10 +468,8 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, if (err) goto out; - /* - * Feed the data into the command read/write port reg - * in chunks of 64 bytes - */ + /* Feed the data into the command read/write port reg + * in chunks of 64 bytes */ memset(temp, 0, sizeof(temp)); memcpy(temp, fw, min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); @@ -515,11 +491,9 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, fw += HELPER_FW_LOAD_CHUNK_SZ; } - /* - * Once the helper / single stage firmware download is complete, + /* Once the helper / single stage firmware download is complete, * write 0 to scratch pad 1 and interrupt the - * bootloader. This completes the helper download. - */ + * bootloader. This completes the helper download. */ err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); if (err) goto out; @@ -539,20 +513,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, return err; } -/* - * Returns the length of the next packet the firmware expects us to send. - * Sets crc_err if the previous transfer had a CRC error. - */ +/* Returns the length of the next packet the firmware expects us to send + * Sets crc_err if the previous transfer had a CRC error. */ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, int *crc_err) { u16 len; int err = 0; - /* - * wait until the host interrupt status register indicates - * that we are ready to download - */ + /* wait until the host interrupt status register indicates + * that we are ready to download */ err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, IF_SPI_HIST_CMD_DOWNLOAD_RDY, IF_SPI_HIST_CMD_DOWNLOAD_RDY); @@ -613,10 +583,8 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, goto out; } if (bytes < 0) { - /* - * If there are no more bytes left, we would normally - * expect to have terminated with len = 0 - */ + /* If there are no more bytes left, we would normally + * expect to have terminated with len = 0 */ lbs_pr_err("Firmware load wants more bytes " "than we have to offer.\n"); break; @@ -688,18 +656,14 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) u16 len; u8 i; - /* - * We need a buffer big enough to handle whatever people send to - * hw_host_to_card - */ + /* We need a buffer big enough to handle whatever people send to + * hw_host_to_card */ BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE); BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); - /* - * It's just annoying if the buffer size isn't a multiple of 4, because - * then we might have len < IF_SPI_CMD_BUF_SIZE but - * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE - */ + /* It's just annoying if the buffer size isn't a multiple of 4, because + * then we might have len < IF_SPI_CMD_BUF_SIZE but + * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0); lbs_deb_enter(LBS_DEB_SPI); @@ -870,10 +834,8 @@ static void if_spi_host_to_card_worker(struct work_struct *work) lbs_deb_enter(LBS_DEB_SPI); - /* - * Read the host interrupt status register to see what we - * can do. - */ + /* Read the host interrupt status register to see what we + * can do. */ err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, &hiStatus); if (err) { @@ -892,15 +854,12 @@ static void if_spi_host_to_card_worker(struct work_struct *work) goto err; } - /* - * workaround: in PS mode, the card does not set the Command - * Download Ready bit, but it sets TX Download Ready. - */ + /* workaround: in PS mode, the card does not set the Command + * Download Ready bit, but it sets TX Download Ready. */ if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || (card->priv->psstate != PS_STATE_FULL_POWER && (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { - /* - * This means two things. First of all, + /* This means two things. First of all, * if there was a previous command sent, the card has * successfully received it. * Secondly, it is now ready to download another @@ -908,7 +867,8 @@ static void if_spi_host_to_card_worker(struct work_struct *work) */ lbs_host_to_card_done(card->priv); - /* Do we have any command packets from the host to send? */ + /* Do we have any command packets from the host to + * send? */ packet = NULL; spin_lock_irqsave(&card->buffer_lock, flags); if (!list_empty(&card->cmd_packet_list)) { @@ -922,7 +882,8 @@ static void if_spi_host_to_card_worker(struct work_struct *work) if_spi_h2c(card, packet, MVMS_CMD); } if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { - /* Do we have any data packets from the host to send? */ + /* Do we have any data packets from the host to + * send? */ packet = NULL; spin_lock_irqsave(&card->buffer_lock, flags); if (!list_empty(&card->data_packet_list)) { @@ -949,8 +910,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) * Host to Card * * Called from Libertas to transfer some data to the WLAN device - * We can't sleep here. - */ + * We can't sleep here. */ static int if_spi_host_to_card(struct lbs_private *priv, u8 type, u8 *buf, u16 nb) { @@ -1097,28 +1057,6 @@ static int if_spi_init_card(struct if_spi_card *card) return err; } -static void if_spi_resume_worker(struct work_struct *work) -{ - struct if_spi_card *card; - - card = container_of(work, struct if_spi_card, resume_work); - - if (card->suspended) { - if (card->pdata->setup) - card->pdata->setup(card->spi); - - /* Init card ... */ - if_spi_init_card(card); - - enable_irq(card->spi->irq); - - /* And resume it ... */ - lbs_resume(card->priv); - - card->suspended = 0; - } -} - static int __devinit if_spi_probe(struct spi_device *spi) { struct if_spi_card *card; @@ -1161,17 +1099,14 @@ static int __devinit if_spi_probe(struct spi_device *spi) if (err) goto free_card; - /* - * Register our card with libertas. - * This will call alloc_etherdev. - */ + /* Register our card with libertas. + * This will call alloc_etherdev */ priv = lbs_add_card(card, &spi->dev); if (!priv) { err = -ENOMEM; goto free_card; } card->priv = priv; - priv->setup_fw_on_resume = 1; priv->card = card; priv->hw_host_to_card = if_spi_host_to_card; priv->enter_deep_sleep = NULL; @@ -1182,7 +1117,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) /* Initialize interrupt handling stuff. */ card->workqueue = create_workqueue("libertas_spi"); INIT_WORK(&card->packet_work, if_spi_host_to_card_worker); - INIT_WORK(&card->resume_work, if_spi_resume_worker); err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); @@ -1191,11 +1125,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) goto terminate_workqueue; } - /* - * Start the card. + /* Start the card. * This will call register_netdev, and we'll start - * getting interrupts... - */ + * getting interrupts... */ err = lbs_start_card(priv); if (err) goto release_irq; @@ -1229,8 +1161,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) lbs_deb_spi("libertas_spi_remove\n"); lbs_deb_enter(LBS_DEB_SPI); - cancel_work_sync(&card->resume_work); - lbs_stop_card(priv); lbs_remove_card(priv); /* will call free_netdev */ @@ -1244,40 +1174,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) return 0; } -static int if_spi_suspend(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct if_spi_card *card = spi_get_drvdata(spi); - - if (!card->suspended) { - lbs_suspend(card->priv); - flush_workqueue(card->workqueue); - disable_irq(spi->irq); - - if (card->pdata->teardown) - card->pdata->teardown(spi); - card->suspended = 1; - } - - return 0; -} - -static int if_spi_resume(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct if_spi_card *card = spi_get_drvdata(spi); - - /* Schedule delayed work */ - schedule_work(&card->resume_work); - - return 0; -} - -static const struct dev_pm_ops if_spi_pm_ops = { - .suspend = if_spi_suspend, - .resume = if_spi_resume, -}; - static struct spi_driver libertas_spi_driver = { .probe = if_spi_probe, .remove = __devexit_p(libertas_spi_remove), @@ -1285,7 +1181,6 @@ static struct spi_driver libertas_spi_driver = { .name = "libertas_spi", .bus = &spi_bus_type, .owner = THIS_MODULE, - .pm = &if_spi_pm_ops, }, }; diff --git a/trunk/drivers/net/wireless/libertas/if_spi.h b/trunk/drivers/net/wireless/libertas/if_spi.h index 9745bd407d76..8b1417d3b71b 100644 --- a/trunk/drivers/net/wireless/libertas/if_spi.h +++ b/trunk/drivers/net/wireless/libertas/if_spi.h @@ -86,34 +86,34 @@ #define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff) /***************** IF_SPI_HOST_INT_CTRL_REG *****************/ -/* Host Interrupt Control bit : Wake up */ +/** Host Interrupt Control bit : Wake up */ #define IF_SPI_HICT_WAKE_UP (1<<0) -/* Host Interrupt Control bit : WLAN ready */ +/** Host Interrupt Control bit : WLAN ready */ #define IF_SPI_HICT_WLAN_READY (1<<1) /*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */ /*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */ /*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */ -/* Host Interrupt Control bit : Tx auto download */ +/** Host Interrupt Control bit : Tx auto download */ #define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5) -/* Host Interrupt Control bit : Rx auto upload */ +/** Host Interrupt Control bit : Rx auto upload */ #define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6) -/* Host Interrupt Control bit : Command auto download */ +/** Host Interrupt Control bit : Command auto download */ #define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7) -/* Host Interrupt Control bit : Command auto upload */ +/** Host Interrupt Control bit : Command auto upload */ #define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8) /***************** IF_SPI_CARD_INT_CAUSE_REG *****************/ -/* Card Interrupt Case bit : Tx download over */ +/** Card Interrupt Case bit : Tx download over */ #define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0) -/* Card Interrupt Case bit : Rx upload over */ +/** Card Interrupt Case bit : Rx upload over */ #define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1) -/* Card Interrupt Case bit : Command download over */ +/** Card Interrupt Case bit : Command download over */ #define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2) -/* Card Interrupt Case bit : Host event */ +/** Card Interrupt Case bit : Host event */ #define IF_SPI_CIC_HOST_EVENT (1<<3) -/* Card Interrupt Case bit : Command upload over */ +/** Card Interrupt Case bit : Command upload over */ #define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4) -/* Card Interrupt Case bit : Power down */ +/** Card Interrupt Case bit : Power down */ #define IF_SPI_CIC_POWER_DOWN (1<<5) /***************** IF_SPI_CARD_INT_STATUS_REG *****************/ @@ -138,51 +138,51 @@ #define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10) /***************** IF_SPI_HOST_INT_STATUS_REG *****************/ -/* Host Interrupt Status bit : Tx download ready */ +/** Host Interrupt Status bit : Tx download ready */ #define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0) -/* Host Interrupt Status bit : Rx upload ready */ +/** Host Interrupt Status bit : Rx upload ready */ #define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1) -/* Host Interrupt Status bit : Command download ready */ +/** Host Interrupt Status bit : Command download ready */ #define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2) -/* Host Interrupt Status bit : Card event */ +/** Host Interrupt Status bit : Card event */ #define IF_SPI_HIST_CARD_EVENT (1<<3) -/* Host Interrupt Status bit : Command upload ready */ +/** Host Interrupt Status bit : Command upload ready */ #define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4) -/* Host Interrupt Status bit : I/O write FIFO overflow */ +/** Host Interrupt Status bit : I/O write FIFO overflow */ #define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5) -/* Host Interrupt Status bit : I/O read FIFO underflow */ +/** Host Interrupt Status bit : I/O read FIFO underflow */ #define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6) -/* Host Interrupt Status bit : Data write FIFO overflow */ +/** Host Interrupt Status bit : Data write FIFO overflow */ #define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7) -/* Host Interrupt Status bit : Data read FIFO underflow */ +/** Host Interrupt Status bit : Data read FIFO underflow */ #define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8) -/* Host Interrupt Status bit : Command write FIFO overflow */ +/** Host Interrupt Status bit : Command write FIFO overflow */ #define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9) -/* Host Interrupt Status bit : Command read FIFO underflow */ +/** Host Interrupt Status bit : Command read FIFO underflow */ #define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10) /***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/ -/* Host Interrupt Status Mask bit : Tx download ready */ +/** Host Interrupt Status Mask bit : Tx download ready */ #define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0) -/* Host Interrupt Status Mask bit : Rx upload ready */ +/** Host Interrupt Status Mask bit : Rx upload ready */ #define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1) -/* Host Interrupt Status Mask bit : Command download ready */ +/** Host Interrupt Status Mask bit : Command download ready */ #define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2) -/* Host Interrupt Status Mask bit : Card event */ +/** Host Interrupt Status Mask bit : Card event */ #define IF_SPI_HISM_CARDEVENT (1<<3) -/* Host Interrupt Status Mask bit : Command upload ready */ +/** Host Interrupt Status Mask bit : Command upload ready */ #define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4) -/* Host Interrupt Status Mask bit : I/O write FIFO overflow */ +/** Host Interrupt Status Mask bit : I/O write FIFO overflow */ #define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5) -/* Host Interrupt Status Mask bit : I/O read FIFO underflow */ +/** Host Interrupt Status Mask bit : I/O read FIFO underflow */ #define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6) -/* Host Interrupt Status Mask bit : Data write FIFO overflow */ +/** Host Interrupt Status Mask bit : Data write FIFO overflow */ #define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7) -/* Host Interrupt Status Mask bit : Data write FIFO underflow */ +/** Host Interrupt Status Mask bit : Data write FIFO underflow */ #define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8) -/* Host Interrupt Status Mask bit : Command write FIFO overflow */ +/** Host Interrupt Status Mask bit : Command write FIFO overflow */ #define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9) -/* Host Interrupt Status Mask bit : Command write FIFO underflow */ +/** Host Interrupt Status Mask bit : Command write FIFO underflow */ #define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10) /***************** IF_SPI_SPU_BUS_MODE_REG *****************/ diff --git a/trunk/drivers/net/wireless/libertas/if_usb.c b/trunk/drivers/net/wireless/libertas/if_usb.c index e1e2128f4113..6524c70363d9 100644 --- a/trunk/drivers/net/wireless/libertas/if_usb.c +++ b/trunk/drivers/net/wireless/libertas/if_usb.c @@ -1,6 +1,6 @@ -/* - * This file contains functions used in USB interface module. - */ +/** + * This file contains functions used in USB interface module. + */ #include #include #include @@ -66,7 +66,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); /* sysfs hooks */ -/* +/** * Set function to write firmware to device's persistent memory */ static ssize_t if_usb_firmware_set(struct device *dev, @@ -85,7 +85,7 @@ static ssize_t if_usb_firmware_set(struct device *dev, return ret; } -/* +/** * lbs_flash_fw attribute to be exported per ethX interface through sysfs * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to * the device's persistent memory: @@ -94,14 +94,7 @@ static ssize_t if_usb_firmware_set(struct device *dev, static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); /** - * if_usb_boot2_set - write firmware to device's persistent memory - * - * @dev: target device - * @attr: device attributes - * @buf: firmware buffer to write - * @count: number of bytes to write - * - * returns: number of bytes written or negative error code + * Set function to write firmware to device's persistent memory */ static ssize_t if_usb_boot2_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -119,7 +112,7 @@ static ssize_t if_usb_boot2_set(struct device *dev, return ret; } -/* +/** * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware * to the device's persistent memory: @@ -128,10 +121,9 @@ static ssize_t if_usb_boot2_set(struct device *dev, static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set); /** - * if_usb_write_bulk_callback - callback function to handle the status - * of the URB - * @urb: pointer to &urb structure - * returns: N/A + * @brief call back function to handle the status of the URB + * @param urb pointer to urb structure + * @return N/A */ static void if_usb_write_bulk_callback(struct urb *urb) { @@ -158,9 +150,9 @@ static void if_usb_write_bulk_callback(struct urb *urb) } /** - * if_usb_free - free tx/rx urb, skb and rx buffer - * @cardp: pointer to &if_usb_card - * returns: N/A + * @brief free tx/rx urb, skb and rx buffer + * @param cardp pointer if_usb_card + * @return N/A */ static void if_usb_free(struct if_usb_card *cardp) { @@ -239,10 +231,10 @@ static void if_usb_reset_olpc_card(struct lbs_private *priv) #endif /** - * if_usb_probe - sets the configuration values - * @intf: &usb_interface pointer - * @id: pointer to usb_device_id - * returns: 0 on success, error code on failure + * @brief sets the configuration values + * @param ifnum interface number + * @param id pointer to usb_device_id + * @return 0 on success, error code on failure */ static int if_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -374,9 +366,9 @@ static int if_usb_probe(struct usb_interface *intf, } /** - * if_usb_disconnect - free resource and cleanup - * @intf: USB interface structure - * returns: N/A + * @brief free resource and cleanup + * @param intf USB interface structure + * @return N/A */ static void if_usb_disconnect(struct usb_interface *intf) { @@ -406,9 +398,9 @@ static void if_usb_disconnect(struct usb_interface *intf) } /** - * if_usb_send_fw_pkt - download FW - * @cardp: pointer to &struct if_usb_card - * returns: 0 + * @brief This function download FW + * @param priv pointer to struct lbs_private + * @return 0 */ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) { @@ -494,11 +486,11 @@ static int if_usb_reset_device(struct if_usb_card *cardp) } /** - * usb_tx_block - transfer the data to the device - * @cardp: pointer to &struct if_usb_card - * @payload: pointer to payload data - * @nb: data length - * returns: 0 for success or negative error code + * @brief This function transfer the data to the device. + * @param priv pointer to struct lbs_private + * @param payload pointer to payload data + * @param nb data length + * @return 0 or -1 */ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb) { @@ -735,11 +727,11 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, } /** - * if_usb_receive - read the packet into the upload buffer, - * wake up the main thread and initialise the Rx callack + * @brief This function reads of the packet into the upload buff, + * wake up the main thread and initialise the Rx callack. * - * @urb: pointer to &struct urb - * returns: N/A + * @param urb pointer to struct urb + * @return N/A */ static void if_usb_receive(struct urb *urb) { @@ -810,12 +802,12 @@ static void if_usb_receive(struct urb *urb) } /** - * if_usb_host_to_card - downloads data to FW - * @priv: pointer to &struct lbs_private structure - * @type: type of data - * @payload: pointer to data buffer - * @nb: number of bytes - * returns: 0 for success or negative error code + * @brief This function downloads data to FW + * @param priv pointer to struct lbs_private structure + * @param type type of data + * @param buf pointer to data buffer + * @param len number of bytes + * @return 0 or -1 */ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, uint8_t *payload, uint16_t nb) @@ -839,11 +831,10 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, } /** - * if_usb_issue_boot_command - issues Boot command to the Boot2 code - * @cardp: pointer to &if_usb_card - * @ivalue: 1:Boot from FW by USB-Download - * 2:Boot from FW in EEPROM - * returns: 0 for success or negative error code + * @brief This function issues Boot command to the Boot2 code + * @param ivalue 1:Boot from FW by USB-Download + * 2:Boot from FW in EEPROM + * @return 0 */ static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) { @@ -862,11 +853,11 @@ static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) /** - * check_fwfile_format - check the validity of Boot2/FW image + * @brief This function checks the validity of Boot2/FW image. * - * @data: pointer to image - * @totlen: image length - * returns: 0 (good) or 1 (failure) + * @param data pointer to image + * len image length + * @return 0 or -1 */ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) { @@ -910,13 +901,13 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) /** -* if_usb_prog_firmware - programs the firmware subject to cmd +* @brief This function programs the firmware subject to cmd * -* @cardp: the if_usb_card descriptor -* @fwname: firmware or boot2 image file name -* @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, -* or BOOT_CMD_UPDATE_BOOT2. -* returns: 0 or error code +* @param cardp the if_usb_card descriptor +* fwname firmware or boot2 image file name +* cmd either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, +* or BOOT_CMD_UPDATE_BOOT2. +* @return 0 or error code */ static int if_usb_prog_firmware(struct if_usb_card *cardp, const char *fwname, int cmd) diff --git a/trunk/drivers/net/wireless/libertas/if_usb.h b/trunk/drivers/net/wireless/libertas/if_usb.h index 6e42eac331de..d819e7e3c9aa 100644 --- a/trunk/drivers/net/wireless/libertas/if_usb.h +++ b/trunk/drivers/net/wireless/libertas/if_usb.h @@ -6,9 +6,9 @@ struct lbs_private; -/* - * This file contains definition for USB interface. - */ +/** + * This file contains definition for USB interface. + */ #define CMD_TYPE_REQUEST 0xF00DFACE #define CMD_TYPE_DATA 0xBEADC0DE #define CMD_TYPE_INDICATION 0xBEEFFACE @@ -40,7 +40,7 @@ struct bootcmdresp uint8_t pad[2]; }; -/* USB card description structure*/ +/** USB card description structure*/ struct if_usb_card { struct usb_device *udev; uint32_t model; /* MODEL_* */ @@ -77,7 +77,7 @@ struct if_usb_card { __le16 boot2_version; }; -/* fwheader */ +/** fwheader */ struct fwheader { __le32 dnldcmd; __le32 baseaddr; @@ -86,14 +86,14 @@ struct fwheader { }; #define FW_MAX_DATA_BLK_SIZE 600 -/* FWData */ +/** FWData */ struct fwdata { struct fwheader hdr; __le32 seqnum; uint8_t data[0]; }; -/* fwsyncheader */ +/** fwsyncheader */ struct fwsyncheader { __le32 cmd; __le32 seqnum; diff --git a/trunk/drivers/net/wireless/libertas/main.c b/trunk/drivers/net/wireless/libertas/main.c index ed57cf863b69..ca8149cd5bd9 100644 --- a/trunk/drivers/net/wireless/libertas/main.c +++ b/trunk/drivers/net/wireless/libertas/main.c @@ -1,8 +1,8 @@ -/* - * This file contains the major functions in WLAN - * driver. It includes init, exit, open, close and main - * thread etc.. - */ +/** + * This file contains the major functions in WLAN + * driver. It includes init, exit, open, close and main + * thread etc.. + */ #include #include @@ -35,20 +35,18 @@ EXPORT_SYMBOL_GPL(lbs_debug); module_param_named(libertas_debug, lbs_debug, int, 0644); -/* - * This global structure is used to send the confirm_sleep command as - * fast as possible down to the firmware. - */ +/* This global structure is used to send the confirm_sleep command as + * fast as possible down to the firmware. */ struct cmd_confirm_sleep confirm_sleep; -/* +/** * the table to keep region code */ u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; -/* +/** * FW rate table. FW refers to rates by their index in this table, not by the * rate value itself. Values of 0x00 are * reserved positions. @@ -59,10 +57,10 @@ static u8 fw_data_rates[MAX_RATES] = }; /** - * lbs_fw_index_to_data_rate - use index to get the data rate + * @brief use index to get the data rate * - * @idx: The index of data rate - * returns: data rate or 0 + * @param idx The index of data rate + * @return data rate or 0 */ u32 lbs_fw_index_to_data_rate(u8 idx) { @@ -72,10 +70,10 @@ u32 lbs_fw_index_to_data_rate(u8 idx) } /** - * lbs_data_rate_to_fw_index - use rate to get the index + * @brief use rate to get the index * - * @rate: data rate - * returns: index or 0 + * @param rate data rate + * @return index or 0 */ u8 lbs_data_rate_to_fw_index(u32 rate) { @@ -93,10 +91,10 @@ u8 lbs_data_rate_to_fw_index(u32 rate) /** - * lbs_dev_open - open the ethX interface + * @brief This function opens the ethX interface * - * @dev: A pointer to &net_device structure - * returns: 0 or -EBUSY if monitor mode active + * @param dev A pointer to net_device structure + * @return 0 or -EBUSY if monitor mode active */ static int lbs_dev_open(struct net_device *dev) { @@ -122,10 +120,10 @@ static int lbs_dev_open(struct net_device *dev) } /** - * lbs_eth_stop - close the ethX interface + * @brief This function closes the ethX interface * - * @dev: A pointer to &net_device structure - * returns: 0 + * @param dev A pointer to net_device structure + * @return 0 */ static int lbs_eth_stop(struct net_device *dev) { @@ -338,12 +336,12 @@ void lbs_set_multicast_list(struct net_device *dev) } /** - * lbs_thread - handles the major jobs in the LBS driver. + * @brief This function handles the major jobs in the LBS driver. * It handles all events generated by firmware, RX data received * from firmware and TX data sent from kernel. * - * @data: A pointer to &lbs_thread structure - * returns: 0 + * @param data A pointer to lbs_thread structure + * @return 0 */ static int lbs_thread(void *data) { @@ -542,11 +540,11 @@ static int lbs_thread(void *data) } /** - * lbs_setup_firmware - gets the HW spec from the firmware and sets - * some basic parameters + * @brief This function gets the HW spec from the firmware and sets + * some basic parameters. * - * @priv: A pointer to &struct lbs_private structure - * returns: 0 or -1 + * @param priv A pointer to struct lbs_private structure + * @return 0 or -1 */ static int lbs_setup_firmware(struct lbs_private *priv) { @@ -632,10 +630,8 @@ int lbs_resume(struct lbs_private *priv) EXPORT_SYMBOL_GPL(lbs_resume); /** - * lbs_cmd_timeout_handler - handles the timeout of command sending. - * It will re-send the same command again. - * - * @data: &struct lbs_private pointer + * This function handles the timeout of command sending. + * It will re-send the same command again. */ static void lbs_cmd_timeout_handler(unsigned long data) { @@ -659,10 +655,8 @@ static void lbs_cmd_timeout_handler(unsigned long data) } /** - * auto_deepsleep_timer_fn - put the device back to deep sleep mode when - * timer expires and no activity (command, event, data etc.) is detected. - * @data: &struct lbs_private pointer - * returns: N/A + * This function put the device back to deep sleep mode when timer expires + * and no activity (command, event, data etc.) is detected. */ static void auto_deepsleep_timer_fn(unsigned long data) { @@ -798,12 +792,11 @@ static const struct net_device_ops lbs_netdev_ops = { }; /** - * lbs_add_card - adds the card. It will probe the + * @brief This function adds the card. it will probe the * card, allocate the lbs_priv and initialize the device. * - * @card: A pointer to card - * @dmdev: A pointer to &struct device - * returns: A pointer to &struct lbs_private structure + * @param card A pointer to card + * @return A pointer to struct lbs_private structure */ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) { @@ -1064,19 +1057,19 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) EXPORT_SYMBOL_GPL(lbs_notify_command_response); /** - * lbs_get_firmware - Retrieves two-stage firmware + * @brief Retrieves two-stage firmware * - * @dev: A pointer to &device structure - * @user_helper: User-defined helper firmware file - * @user_mainfw: User-defined main firmware file - * @card_model: Bus-specific card model ID used to filter firmware table - * elements - * @fw_table: Table of firmware file names and device model numbers - * terminated by an entry with a NULL helper name - * @helper: On success, the helper firmware; caller must free - * @mainfw: On success, the main firmware; caller must free + * @param dev A pointer to device structure + * @param user_helper User-defined helper firmware file + * @param user_mainfw User-defined main firmware file + * @param card_model Bus-specific card model ID used to filter firmware table + * elements + * @param fw_table Table of firmware file names and device model numbers + * terminated by an entry with a NULL helper name + * @param helper On success, the helper firmware; caller must free + * @param mainfw On success, the main firmware; caller must free * - * returns: 0 on success, non-zero on failure + * @return 0 on success, non-zero on failure */ int lbs_get_firmware(struct device *dev, const char *user_helper, const char *user_mainfw, u32 card_model, diff --git a/trunk/drivers/net/wireless/libertas/mesh.c b/trunk/drivers/net/wireless/libertas/mesh.c index a0804d12bf20..9d097b9c8005 100644 --- a/trunk/drivers/net/wireless/libertas/mesh.c +++ b/trunk/drivers/net/wireless/libertas/mesh.c @@ -16,15 +16,12 @@ * Mesh sysfs support */ -/* +/** * Attributes exported through sysfs */ /** - * lbs_anycast_get - Get function for sysfs attribute anycast_mask - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute anycast_mask */ static ssize_t lbs_anycast_get(struct device *dev, struct device_attribute *attr, char * buf) @@ -43,11 +40,7 @@ static ssize_t lbs_anycast_get(struct device *dev, } /** - * lbs_anycast_set - Set function for sysfs attribute anycast_mask - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute anycast_mask */ static ssize_t lbs_anycast_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) @@ -69,10 +62,7 @@ static ssize_t lbs_anycast_set(struct device *dev, } /** - * lbs_prb_rsp_limit_get - Get function for sysfs attribute prb_rsp_limit - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute prb_rsp_limit */ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -95,11 +85,7 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, } /** - * lbs_prb_rsp_limit_set - Set function for sysfs attribute prb_rsp_limit - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute prb_rsp_limit */ static ssize_t lbs_prb_rsp_limit_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -128,10 +114,7 @@ static ssize_t lbs_prb_rsp_limit_set(struct device *dev, } /** - * lbs_mesh_get - Get function for sysfs attribute mesh - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * Get function for sysfs attribute mesh */ static ssize_t lbs_mesh_get(struct device *dev, struct device_attribute *attr, char * buf) @@ -141,11 +124,7 @@ static ssize_t lbs_mesh_get(struct device *dev, } /** - * lbs_mesh_set - Set function for sysfs attribute mesh - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * Set function for sysfs attribute mesh */ static ssize_t lbs_mesh_set(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) @@ -172,19 +151,19 @@ static ssize_t lbs_mesh_set(struct device *dev, return count; } -/* +/** * lbs_mesh attribute to be exported per ethX interface * through sysfs (/sys/class/net/ethX/lbs_mesh) */ static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); -/* +/** * anycast_mask attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/anycast_mask) */ static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); -/* +/** * prb_rsp_limit attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/prb_rsp_limit) */ @@ -295,10 +274,10 @@ int lbs_deinit_mesh(struct lbs_private *priv) /** - * lbs_mesh_stop - close the mshX interface + * @brief This function closes the mshX interface * - * @dev: A pointer to &net_device structure - * returns: 0 + * @param dev A pointer to net_device structure + * @return 0 */ static int lbs_mesh_stop(struct net_device *dev) { @@ -322,10 +301,10 @@ static int lbs_mesh_stop(struct net_device *dev) } /** - * lbs_mesh_dev_open - open the mshX interface + * @brief This function opens the mshX interface * - * @dev: A pointer to &net_device structure - * returns: 0 or -EBUSY if monitor mode active + * @param dev A pointer to net_device structure + * @return 0 or -EBUSY if monitor mode active */ static int lbs_mesh_dev_open(struct net_device *dev) { @@ -363,10 +342,10 @@ static const struct net_device_ops mesh_netdev_ops = { }; /** - * lbs_add_mesh - add mshX interface + * @brief This function adds mshX interface * - * @priv: A pointer to the &struct lbs_private structure - * returns: 0 if successful, -X otherwise + * @param priv A pointer to the struct lbs_private structure + * @return 0 if successful, -X otherwise */ int lbs_add_mesh(struct lbs_private *priv) { @@ -477,13 +456,13 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, */ /** - * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries + * @brief Add or delete Mesh Blinding Table entries * - * @priv: A pointer to &struct lbs_private structure - * @add: TRUE to add the entry, FALSE to delete it - * @addr1: Destination address to blind or unblind + * @param priv A pointer to struct lbs_private structure + * @param add TRUE to add the entry, FALSE to delete it + * @param addr1 Destination address to blind or unblind * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) { @@ -514,11 +493,11 @@ int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) } /** - * lbs_mesh_bt_reset - Reset/clear the mesh blinding table + * @brief Reset/clear the mesh blinding table * - * @priv: A pointer to &struct lbs_private structure + * @param priv A pointer to struct lbs_private structure * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_mesh_bt_reset(struct lbs_private *priv) { @@ -538,18 +517,17 @@ int lbs_mesh_bt_reset(struct lbs_private *priv) } /** - * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh - * blinding table + * @brief Gets the inverted status of the mesh blinding table * - * Normally the firmware "blinds" or ignores traffic from mesh nodes in the - * table, but an inverted table allows *only* traffic from nodes listed in - * the table. + * Normally the firmware "blinds" or ignores traffic from mesh nodes in the + * table, but an inverted table allows *only* traffic from nodes listed in + * the table. * - * @priv: A pointer to &struct lbs_private structure - * @inverted: On success, TRUE if the blinding table is inverted, - * FALSE if it is not inverted + * @param priv A pointer to struct lbs_private structure + * @param invert On success, TRUE if the blinding table is inverted, + * FALSE if it is not inverted * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) { @@ -573,19 +551,18 @@ int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) } /** - * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh - * blinding table + * @brief Sets the inverted status of the mesh blinding table * - * Normally the firmware "blinds" or ignores traffic from mesh nodes in the - * table, but an inverted table allows *only* traffic from nodes listed in - * the table. + * Normally the firmware "blinds" or ignores traffic from mesh nodes in the + * table, but an inverted table allows *only* traffic from nodes listed in + * the table. * - * @priv: A pointer to &struct lbs_private structure - * @inverted: TRUE to invert the blinding table (only traffic from - * listed nodes allowed), FALSE to return it - * to normal state (listed nodes ignored) + * @param priv A pointer to struct lbs_private structure + * @param invert TRUE to invert the blinding table (only traffic from + * listed nodes allowed), FALSE to return it + * to normal state (listed nodes ignored) * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) { @@ -606,13 +583,13 @@ int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) } /** - * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table + * @brief List an entry in the mesh blinding table * - * @priv: A pointer to &struct lbs_private structure - * @id: The ID of the entry to list - * @addr1: MAC address associated with the table entry + * @param priv A pointer to struct lbs_private structure + * @param id The ID of the entry to list + * @param addr1 MAC address associated with the table entry * - * returns: 0 on success, error on failure + * @return 0 on success, error on failure */ int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) { @@ -637,14 +614,14 @@ int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) } /** - * lbs_cmd_fwt_access - Access the mesh forwarding table + * @brief Access the mesh forwarding table * - * @priv: A pointer to &struct lbs_private structure - * @cmd_action: The forwarding table action to perform - * @cmd: The pre-filled FWT_ACCESS command + * @param priv A pointer to struct lbs_private structure + * @param cmd_action The forwarding table action to perform + * @param cmd The pre-filled FWT_ACCESS command * - * returns: 0 on success and 'cmd' will be filled with the - * firmware's response + * @return 0 on success and 'cmd' will be filled with the + * firmware's response */ int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, struct cmd_ds_fwt_access *cmd) @@ -797,10 +774,7 @@ static int mesh_get_default_parameters(struct device *dev, } /** - * bootflag_get - Get function for sysfs attribute bootflag - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute bootflag */ static ssize_t bootflag_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -817,11 +791,7 @@ static ssize_t bootflag_get(struct device *dev, } /** - * bootflag_set - Set function for sysfs attribute bootflag - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute bootflag */ static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -847,10 +817,7 @@ static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, } /** - * boottime_get - Get function for sysfs attribute boottime - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute boottime */ static ssize_t boottime_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -867,11 +834,7 @@ static ssize_t boottime_get(struct device *dev, } /** - * boottime_set - Set function for sysfs attribute boottime - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute boottime */ static ssize_t boottime_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -906,10 +869,7 @@ static ssize_t boottime_set(struct device *dev, } /** - * channel_get - Get function for sysfs attribute channel - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute channel */ static ssize_t channel_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -926,11 +886,7 @@ static ssize_t channel_get(struct device *dev, } /** - * channel_set - Set function for sysfs attribute channel - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute channel */ static ssize_t channel_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -956,10 +912,7 @@ static ssize_t channel_set(struct device *dev, struct device_attribute *attr, } /** - * mesh_id_get - Get function for sysfs attribute mesh_id - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute mesh_id */ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -985,11 +938,7 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, } /** - * mesh_id_set - Set function for sysfs attribute mesh_id - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute mesh_id */ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1031,10 +980,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, } /** - * protocol_id_get - Get function for sysfs attribute protocol_id - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute protocol_id */ static ssize_t protocol_id_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -1051,11 +997,7 @@ static ssize_t protocol_id_get(struct device *dev, } /** - * protocol_id_set - Set function for sysfs attribute protocol_id - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute protocol_id */ static ssize_t protocol_id_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1092,10 +1034,7 @@ static ssize_t protocol_id_set(struct device *dev, } /** - * metric_id_get - Get function for sysfs attribute metric_id - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute metric_id */ static ssize_t metric_id_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -1112,11 +1051,7 @@ static ssize_t metric_id_get(struct device *dev, } /** - * metric_id_set - Set function for sysfs attribute metric_id - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute metric_id */ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1153,10 +1088,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, } /** - * capability_get - Get function for sysfs attribute capability - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer where data will be returned + * @brief Get function for sysfs attribute capability */ static ssize_t capability_get(struct device *dev, struct device_attribute *attr, char *buf) @@ -1173,11 +1105,7 @@ static ssize_t capability_get(struct device *dev, } /** - * capability_set - Set function for sysfs attribute capability - * @dev: the &struct device - * @attr: device attributes - * @buf: buffer that contains new attribute value - * @count: size of buffer + * @brief Set function for sysfs attribute capability */ static ssize_t capability_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/trunk/drivers/net/wireless/libertas/mesh.h b/trunk/drivers/net/wireless/libertas/mesh.h index ee95c73ed5f4..afb2e8dead3f 100644 --- a/trunk/drivers/net/wireless/libertas/mesh.h +++ b/trunk/drivers/net/wireless/libertas/mesh.h @@ -1,6 +1,6 @@ -/* - * Contains all definitions needed for the Libertas' MESH implementation. - */ +/** + * Contains all definitions needed for the Libertas' MESH implementation. + */ #ifndef _LBS_MESH_H_ #define _LBS_MESH_H_ diff --git a/trunk/drivers/net/wireless/libertas/rx.c b/trunk/drivers/net/wireless/libertas/rx.c index a3f4b55aa41f..a2b1df21d286 100644 --- a/trunk/drivers/net/wireless/libertas/rx.c +++ b/trunk/drivers/net/wireless/libertas/rx.c @@ -1,6 +1,6 @@ -/* - * This file contains the handling of RX in wlan driver. - */ +/** + * This file contains the handling of RX in wlan driver. + */ #include #include #include @@ -40,12 +40,12 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb); /** - * lbs_process_rxed_packet - processes received packet and forwards it - * to kernel/upper layer + * @brief This function processes received packet and forwards it + * to kernel/upper layer * - * @priv: A pointer to &struct lbs_private - * @skb: A pointer to skb which includes the received packet - * returns: 0 or -1 + * @param priv A pointer to struct lbs_private + * @param skb A pointer to skb which includes the received packet + * @return 0 or -1 */ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) { @@ -156,11 +156,11 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) EXPORT_SYMBOL_GPL(lbs_process_rxed_packet); /** - * convert_mv_rate_to_radiotap - converts Tx/Rx rates from Marvell WLAN format - * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) + * @brief This function converts Tx/Rx rates from the Marvell WLAN format + * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) * - * @rate: Input rate - * returns: Output Rate (0 if invalid) + * @param rate Input rate + * @return Output Rate (0 if invalid) */ static u8 convert_mv_rate_to_radiotap(u8 rate) { @@ -196,12 +196,12 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) } /** - * process_rxed_802_11_packet - processes a received 802.11 packet and forwards - * it to kernel/upper layer + * @brief This function processes a received 802.11 packet and forwards it + * to kernel/upper layer * - * @priv: A pointer to &struct lbs_private - * @skb: A pointer to skb which includes the received packet - * returns: 0 or -1 + * @param priv A pointer to struct lbs_private + * @param skb A pointer to skb which includes the received packet + * @return 0 or -1 */ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb) diff --git a/trunk/drivers/net/wireless/libertas/tx.c b/trunk/drivers/net/wireless/libertas/tx.c index bbb95f88dc01..8000ca6165d0 100644 --- a/trunk/drivers/net/wireless/libertas/tx.c +++ b/trunk/drivers/net/wireless/libertas/tx.c @@ -1,6 +1,6 @@ -/* - * This file contains the handling of TX in wlan driver. - */ +/** + * This file contains the handling of TX in wlan driver. + */ #include #include #include @@ -13,11 +13,11 @@ #include "dev.h" /** - * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE - * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) + * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE + * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) * - * @rate: Input rate - * returns: Output Rate (0 if invalid) + * @param rate Input rate + * @return Output Rate (0 if invalid) */ static u32 convert_radiotap_rate_to_mv(u8 rate) { @@ -51,12 +51,12 @@ static u32 convert_radiotap_rate_to_mv(u8 rate) } /** - * lbs_hard_start_xmit - checks the conditions and sends packet to IF - * layer if everything is ok + * @brief This function checks the conditions and sends packet to IF + * layer if everything is ok. * - * @skb: A pointer to skb which includes TX packet - * @dev: A pointer to the &struct net_device - * returns: 0 or -1 + * @param priv A pointer to struct lbs_private structure + * @param skb A pointer to skb which includes TX packet + * @return 0 or -1 */ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -168,13 +168,13 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } /** - * lbs_send_tx_feedback - sends to the host the last transmitted packet, - * filling the radiotap headers with transmission information. + * @brief This function sends to the host the last transmitted packet, + * filling the radiotap headers with transmission information. * - * @priv: A pointer to &struct lbs_private structure - * @try_count: A 32-bit value containing transmission retry status. + * @param priv A pointer to struct lbs_private structure + * @param status A 32 bit value containing transmission status. * - * returns: void + * @returns void */ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) { diff --git a/trunk/drivers/net/wireless/libertas/types.h b/trunk/drivers/net/wireless/libertas/types.h index cf1d9b047ee6..462fbb4cb743 100644 --- a/trunk/drivers/net/wireless/libertas/types.h +++ b/trunk/drivers/net/wireless/libertas/types.h @@ -1,6 +1,6 @@ -/* - * This header file contains definition for global types - */ +/** + * This header file contains definition for global types + */ #ifndef _LBS_TYPES_H_ #define _LBS_TYPES_H_ @@ -54,7 +54,7 @@ union ieee_phy_param_set { struct ieee_ie_ds_param_set ds; } __packed; -/* TLV type ID definition */ +/** TLV type ID definition */ #define PROPRIETARY_TLV_BASE_ID 0x0100 /* Terminating TLV type */ @@ -96,7 +96,7 @@ union ieee_phy_param_set { #define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) #define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) -/* TLV related data structures */ +/** TLV related data structures*/ struct mrvl_ie_header { __le16 type; __le16 len; @@ -177,7 +177,7 @@ struct mrvl_ie_auth_type { __le16 auth; } __packed; -/* Local Power capability */ +/** Local Power capability */ struct mrvl_ie_power_capability { struct mrvl_ie_header header; s8 minpower; @@ -235,11 +235,9 @@ struct mrvl_ie_ledbhv { struct led_bhv ledbhv[1]; } __packed; -/* - * Meant to be packed as the value member of a struct ieee80211_info_element. +/* Meant to be packed as the value member of a struct ieee80211_info_element. * Note that the len member of the ieee80211_info_element varies depending on - * the mesh_id_len - */ + * the mesh_id_len */ struct mrvl_meshie_val { uint8_t oui[3]; uint8_t type; diff --git a/trunk/drivers/net/wireless/mwifiex/11n.c b/trunk/drivers/net/wireless/mwifiex/11n.c deleted file mode 100644 index 1d294cfa6c9b..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/11n.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * Fills HT capability information field, AMPDU Parameters field, HT extended - * capability field, and supported MCS set fields. - * - * HT capability information field, AMPDU Parameters field, supported MCS set - * fields are retrieved from cfg80211 stack - * - * RD responder bit to set to clear in the extended capability header. - */ -void -mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, - struct mwifiex_ie_types_htcap *ht_cap) -{ - uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); - struct ieee80211_supported_band *sband = - priv->wdev->wiphy->bands[radio_type]; - - ht_cap->ht_cap.ampdu_params_info = - (sband->ht_cap.ampdu_factor & - IEEE80211_HT_AMPDU_PARM_FACTOR)| - ((sband->ht_cap.ampdu_density << - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & - IEEE80211_HT_AMPDU_PARM_DENSITY); - - memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs, - sizeof(sband->ht_cap.mcs)); - - if (priv->bss_mode == NL80211_IFTYPE_STATION || - (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ - SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); - - /* Clear RD responder bit */ - ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; - - ht_cap->ht_cap.cap_info = cpu_to_le16(sband->ht_cap.cap); - ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); -} - -/* - * This function returns the pointer to an entry in BA Stream - * table which matches the requested BA status. - */ -static struct mwifiex_tx_ba_stream_tbl * -mwifiex_11n_get_tx_ba_stream_status(struct mwifiex_private *priv, - enum mwifiex_ba_status ba_status) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (tx_ba_tsr_tbl->ba_status == ba_status) { - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, - flags); - return tx_ba_tsr_tbl; - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - return NULL; -} - -/* - * This function handles the command response of delete a block - * ack request. - * - * The function checks the response success status and takes action - * accordingly (send an add BA request in case of success, or recreate - * the deleted stream in case of failure, if the add BA was also - * initiated by us). - */ -int mwifiex_ret_11n_delba(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int tid; - struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; - struct host_cmd_ds_11n_delba *del_ba = - (struct host_cmd_ds_11n_delba *) &resp->params.del_ba; - uint16_t del_ba_param_set = le16_to_cpu(del_ba->del_ba_param_set); - - tid = del_ba_param_set >> DELBA_TID_POS; - if (del_ba->del_result == BA_RESULT_SUCCESS) { - mwifiex_11n_delete_ba_stream_tbl(priv, tid, - del_ba->peer_mac_addr, TYPE_DELBA_SENT, - INITIATOR_BIT(del_ba_param_set)); - - tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv, - BA_STREAM_SETUP_INPROGRESS); - if (tx_ba_tbl) - mwifiex_send_addba(priv, tx_ba_tbl->tid, - tx_ba_tbl->ra); - } else { /* - * In case of failure, recreate the deleted stream in case - * we initiated the ADDBA - */ - if (INITIATOR_BIT(del_ba_param_set)) { - mwifiex_11n_create_tx_ba_stream_tbl(priv, - del_ba->peer_mac_addr, tid, - BA_STREAM_SETUP_INPROGRESS); - - tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv, - BA_STREAM_SETUP_INPROGRESS); - if (tx_ba_tbl) - mwifiex_11n_delete_ba_stream_tbl(priv, - tx_ba_tbl->tid, tx_ba_tbl->ra, - TYPE_DELBA_SENT, true); - } - } - - return 0; -} - -/* - * This function handles the command response of add a block - * ack request. - * - * Handling includes changing the header fields to CPU formats, checking - * the response success status and taking actions accordingly (delete the - * BA stream table in case of failure). - */ -int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int tid; - struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = - (struct host_cmd_ds_11n_addba_rsp *) &resp->params.add_ba_rsp; - struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; - - add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) - & SSN_MASK); - - tid = (le16_to_cpu(add_ba_rsp->block_ack_param_set) - & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { - tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, - add_ba_rsp->peer_mac_addr); - if (tx_ba_tbl) { - dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); - tx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE; - } else { - dev_err(priv->adapter->dev, "BA stream not created\n"); - } - } else { - mwifiex_11n_delete_ba_stream_tbl(priv, tid, - add_ba_rsp->peer_mac_addr, - TYPE_DELBA_SENT, true); - if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) - priv->aggr_prio_tbl[tid].ampdu_ap = - BA_STREAM_NOT_ALLOWED; - } - - return 0; -} - -/* - * This function handles the command response of 11n configuration request. - * - * Handling includes changing the header fields into CPU format. - */ -int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf) -{ - struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL; - struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; - - if (data_buf) { - tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf; - tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap); - tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info); - } - return 0; -} - -/* - * This function prepares command of reconfigure Tx buffer. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting Tx buffer size (for SET only) - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, int cmd_action, - void *data_buf) -{ - struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf; - u16 action = (u16) cmd_action; - u16 buf_size = *((u16 *) data_buf); - - cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN); - tx_buf->action = cpu_to_le16(action); - switch (action) { - case HostCmd_ACT_GEN_SET: - dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size); - tx_buf->buff_size = cpu_to_le16(buf_size); - break; - case HostCmd_ACT_GEN_GET: - default: - tx_buf->buff_size = 0; - break; - } - return 0; -} - -/* - * This function prepares command of AMSDU aggregation control. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting AMSDU control parameters (for SET only) - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, - int cmd_action, void *data_buf) -{ - struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = - &cmd->params.amsdu_aggr_ctrl; - u16 action = (u16) cmd_action; - struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl = - (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; - - cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl) - + S_DS_GEN); - amsdu_ctrl->action = cpu_to_le16(action); - switch (action) { - case HostCmd_ACT_GEN_SET: - amsdu_ctrl->enable = cpu_to_le16(aa_ctrl->enable); - amsdu_ctrl->curr_buf_size = 0; - break; - case HostCmd_ACT_GEN_GET: - default: - amsdu_ctrl->curr_buf_size = 0; - break; - } - return 0; -} - -/* - * This function handles the command response of AMSDU aggregation - * control request. - * - * Handling includes changing the header fields into CPU format. - */ -int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL; - struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = - &resp->params.amsdu_aggr_ctrl; - - if (data_buf) { - amsdu_aggr_ctrl = - (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; - amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable); - amsdu_aggr_ctrl->curr_buf_size = - le16_to_cpu(amsdu_ctrl->curr_buf_size); - } - return 0; -} - -/* - * This function prepares 11n configuration command. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting HT Tx capability and HT Tx information fields - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; - struct mwifiex_ds_11n_tx_cfg *txcfg = - (struct mwifiex_ds_11n_tx_cfg *) data_buf; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN); - htcfg->action = cpu_to_le16(cmd_action); - htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); - htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); - return 0; -} - -/* - * This function appends an 11n TLV to a buffer. - * - * Buffer allocation is responsibility of the calling - * function. No size validation is made here. - * - * The function fills up the following sections, if applicable - - * - HT capability IE - * - HT information IE (with channel list) - * - 20/40 BSS Coexistence IE - * - HT Extended Capabilities IE - */ -int -mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 **buffer) -{ - struct mwifiex_ie_types_htcap *ht_cap; - struct mwifiex_ie_types_htinfo *ht_info; - struct mwifiex_ie_types_chan_list_param_set *chan_list; - struct mwifiex_ie_types_2040bssco *bss_co_2040; - struct mwifiex_ie_types_extcap *ext_cap; - int ret_len = 0; - struct ieee80211_supported_band *sband; - u8 radio_type; - - if (!buffer || !*buffer) - return ret_len; - - radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - sband = priv->wdev->wiphy->bands[radio_type]; - - if (bss_desc->bcn_ht_cap) { - ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; - memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); - ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header), - (u8 *) bss_desc->bcn_ht_cap + - sizeof(struct ieee_types_header), - le16_to_cpu(ht_cap->header.len)); - - mwifiex_fill_cap_info(priv, radio_type, ht_cap); - - *buffer += sizeof(struct mwifiex_ie_types_htcap); - ret_len += sizeof(struct mwifiex_ie_types_htcap); - } - - if (bss_desc->bcn_ht_info) { - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; - memset(ht_info, 0, - sizeof(struct mwifiex_ie_types_htinfo)); - ht_info->header.type = - cpu_to_le16(WLAN_EID_HT_INFORMATION); - ht_info->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_info)); - - memcpy((u8 *) ht_info + - sizeof(struct mwifiex_ie_types_header), - (u8 *) bss_desc->bcn_ht_info + - sizeof(struct ieee_types_header), - le16_to_cpu(ht_info->header.len)); - - if (!(sband->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - ht_info->ht_info.ht_param &= - ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | - IEEE80211_HT_PARAM_CHA_SEC_OFFSET); - - *buffer += sizeof(struct mwifiex_ie_types_htinfo); - ret_len += sizeof(struct mwifiex_ie_types_htinfo); - } - - chan_list = - (struct mwifiex_ie_types_chan_list_param_set *) *buffer; - memset(chan_list, 0, - sizeof(struct mwifiex_ie_types_chan_list_param_set)); - chan_list->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_list->header.len = cpu_to_le16( - sizeof(struct mwifiex_ie_types_chan_list_param_set) - - sizeof(struct mwifiex_ie_types_header)); - chan_list->chan_scan_param[0].chan_number = - bss_desc->bcn_ht_info->control_chan; - chan_list->chan_scan_param[0].radio_type = - mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - - if ((sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - && (bss_desc->bcn_ht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) - SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. - radio_type, - (bss_desc->bcn_ht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); - - *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); - ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set); - } - - if (bss_desc->bcn_bss_co_2040) { - bss_co_2040 = (struct mwifiex_ie_types_2040bssco *) *buffer; - memset(bss_co_2040, 0, - sizeof(struct mwifiex_ie_types_2040bssco)); - bss_co_2040->header.type = cpu_to_le16(WLAN_EID_BSS_COEX_2040); - bss_co_2040->header.len = - cpu_to_le16(sizeof(bss_co_2040->bss_co_2040)); - - memcpy((u8 *) bss_co_2040 + - sizeof(struct mwifiex_ie_types_header), - (u8 *) bss_desc->bcn_bss_co_2040 + - sizeof(struct ieee_types_header), - le16_to_cpu(bss_co_2040->header.len)); - - *buffer += sizeof(struct mwifiex_ie_types_2040bssco); - ret_len += sizeof(struct mwifiex_ie_types_2040bssco); - } - - if (bss_desc->bcn_ext_cap) { - ext_cap = (struct mwifiex_ie_types_extcap *) *buffer; - memset(ext_cap, 0, sizeof(struct mwifiex_ie_types_extcap)); - ext_cap->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY); - ext_cap->header.len = cpu_to_le16(sizeof(ext_cap->ext_cap)); - - memcpy((u8 *) ext_cap + - sizeof(struct mwifiex_ie_types_header), - (u8 *) bss_desc->bcn_ext_cap + - sizeof(struct ieee_types_header), - le16_to_cpu(ext_cap->header.len)); - - *buffer += sizeof(struct mwifiex_ie_types_extcap); - ret_len += sizeof(struct mwifiex_ie_types_extcap); - } - - return ret_len; -} - -/* - * This function reconfigures the Tx buffer size in firmware. - * - * This function prepares a firmware command and issues it, if - * the current Tx buffer size is different from the one requested. - * Maximum configurable Tx buffer size is limited by the HT capability - * field value. - */ -void -mwifiex_cfg_tx_buf(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; - u16 tx_buf = 0; - u16 curr_tx_buf_size = 0; - - if (bss_desc->bcn_ht_cap) { - if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & - IEEE80211_HT_CAP_MAX_AMSDU) - max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K; - else - max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K; - } - - tx_buf = min(priv->adapter->max_tx_buf_size, max_amsdu); - - dev_dbg(priv->adapter->dev, "info: max_amsdu=%d, max_tx_buf=%d\n", - max_amsdu, priv->adapter->max_tx_buf_size); - - if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_2K) - curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_4K) - curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; - else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K) - curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K; - if (curr_tx_buf_size != tx_buf) - mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, &tx_buf); -} - -/* - * This function checks if the given pointer is valid entry of - * Tx BA Stream table. - */ -static int mwifiex_is_tx_ba_stream_ptr_valid(struct mwifiex_private *priv, - struct mwifiex_tx_ba_stream_tbl *tx_tbl_ptr) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (tx_ba_tsr_tbl == tx_tbl_ptr) - return true; - } - - return false; -} - -/* - * This function deletes the given entry in Tx BA Stream table. - * - * The function also performs a validity check on the supplied - * pointer before trying to delete. - */ -void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl) -{ - if (!tx_ba_tsr_tbl && - mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl)) - return; - - dev_dbg(priv->adapter->dev, "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl); - - list_del(&tx_ba_tsr_tbl->list); - - kfree(tx_ba_tsr_tbl); -} - -/* - * This function deletes all the entries in Tx BA Stream table. - */ -void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv) -{ - int i; - struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry_safe(del_tbl_ptr, tmp_node, - &priv->tx_ba_stream_tbl_ptr, list) - mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr); - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); - - for (i = 0; i < MAX_NUM_TID; ++i) - priv->aggr_prio_tbl[i].ampdu_ap = - priv->aggr_prio_tbl[i].ampdu_user; -} - -/* - * This function returns the pointer to an entry in BA Stream - * table which matches the given RA/TID pair. - */ -struct mwifiex_tx_ba_stream_tbl * -mwifiex_11n_get_tx_ba_stream_tbl(struct mwifiex_private *priv, - int tid, u8 *ra) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if ((!memcmp(tx_ba_tsr_tbl->ra, ra, ETH_ALEN)) - && (tx_ba_tsr_tbl->tid == tid)) { - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, - flags); - return tx_ba_tsr_tbl; - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - return NULL; -} - -/* - * This function creates an entry in Tx BA stream table for the - * given RA/TID pair. - */ -void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, - u8 *ra, int tid, - enum mwifiex_ba_status ba_status) -{ - struct mwifiex_tx_ba_stream_tbl *new_node; - unsigned long flags; - - if (!mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ra)) { - new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl), - GFP_ATOMIC); - if (!new_node) { - dev_err(priv->adapter->dev, - "%s: failed to alloc new_node\n", __func__); - return; - } - - INIT_LIST_HEAD(&new_node->list); - - new_node->tid = tid; - new_node->ba_status = ba_status; - memcpy(new_node->ra, ra, ETH_ALEN); - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr); - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - } -} - -/* - * This function sends an add BA request to the given TID/RA pair. - */ -int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) -{ - struct host_cmd_ds_11n_addba_req add_ba_req; - static u8 dialog_tok; - int ret; - - dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); - - add_ba_req.block_ack_param_set = cpu_to_le16( - (u16) ((tid << BLOCKACKPARAM_TID_POS) | - (priv->add_ba_param. - tx_win_size << BLOCKACKPARAM_WINSIZE_POS) | - IMMEDIATE_BLOCK_ACK)); - add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); - - ++dialog_tok; - - if (dialog_tok == 0) - dialog_tok = 1; - - add_ba_req.dialog_token = dialog_tok; - memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); - - /* We don't wait for the response of this command */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ, - 0, 0, &add_ba_req); - - return ret; -} - -/* - * This function sends a delete BA request to the given TID/RA pair. - */ -int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, - int initiator) -{ - struct host_cmd_ds_11n_delba delba; - int ret; - uint16_t del_ba_param_set; - - memset(&delba, 0, sizeof(delba)); - delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); - - del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); - if (initiator) - del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; - else - del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; - - memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); - - /* We don't wait for the response of this command */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, - HostCmd_ACT_GEN_SET, 0, &delba); - - return ret; -} - -/* - * This function handles the command response of a delete BA request. - */ -void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba) -{ - struct host_cmd_ds_11n_delba *cmd_del_ba = - (struct host_cmd_ds_11n_delba *) del_ba; - uint16_t del_ba_param_set = le16_to_cpu(cmd_del_ba->del_ba_param_set); - int tid; - - tid = del_ba_param_set >> DELBA_TID_POS; - - mwifiex_11n_delete_ba_stream_tbl(priv, tid, cmd_del_ba->peer_mac_addr, - TYPE_DELBA_RECEIVE, - INITIATOR_BIT(del_ba_param_set)); -} - -/* - * This function retrieves the Rx reordering table. - */ -int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_rx_reorder_tbl *buf) -{ - int i; - struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf; - struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr; - int count = 0; - unsigned long flags; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr, - list) { - rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid; - memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN); - rx_reo_tbl->start_win = rx_reorder_tbl_ptr->start_win; - rx_reo_tbl->win_size = rx_reorder_tbl_ptr->win_size; - for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) { - if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) - rx_reo_tbl->buffer[i] = true; - else - rx_reo_tbl->buffer[i] = false; - } - rx_reo_tbl++; - count++; - - if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED) - break; - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return count; -} - -/* - * This function retrieves the Tx BA stream table. - */ -int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_tx_ba_stream_tbl *buf) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf; - int count = 0; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid; - dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", - __func__, rx_reo_tbl->tid); - memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); - rx_reo_tbl++; - count++; - if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) - break; - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - return count; -} diff --git a/trunk/drivers/net/wireless/mwifiex/11n.h b/trunk/drivers/net/wireless/mwifiex/11n.h deleted file mode 100644 index a4390a1a2a9f..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/11n.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11N_H_ -#define _MWIFIEX_11N_H_ - -#include "11n_aggr.h" -#include "11n_rxreorder.h" -#include "wmm.h" - -int mwifiex_ret_11n_delba(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, - void *data_buf); -int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf); - -int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 **buffer); -void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); -void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, - struct mwifiex_ie_types_htcap *); -int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, - u16 action, int *htcap_cfg); -void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, - struct mwifiex_tx_ba_stream_tbl - *tx_tbl); -void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv); -struct mwifiex_tx_ba_stream_tbl *mwifiex_11n_get_tx_ba_stream_tbl(struct - mwifiex_private - *priv, int tid, - u8 *ra); -void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, u8 *ra, - int tid, - enum mwifiex_ba_status ba_status); -int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac); -int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, - int initiator); -void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba); -int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_rx_reorder_tbl *buf); -int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_tx_ba_stream_tbl *buf); -int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, - void *data_buf); -int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - int cmd_action, void *data_buf); -int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, - int cmd_action, void *data_buf); - -/* - * This function checks whether AMPDU is allowed or not for a particular TID. - */ -static inline u8 -mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, int tid) -{ - return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) - ? true : false); -} - -/* - * This function checks whether AMSDU is allowed or not for a particular TID. - */ -static inline u8 -mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid) -{ - return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) - && ((priv->is_data_rate_auto) - || !((priv->bitmap_rates[2]) & 0x03))) - ? true : false); -} - -/* - * This function checks whether a space is available for new BA stream or not. - */ -static inline u8 mwifiex_space_avail_for_new_ba_stream( - struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - u8 i; - u32 ba_stream_num = 0; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) - ba_stream_num += mwifiex_wmm_list_len( - (struct list_head *) - &priv->tx_ba_stream_tbl_ptr); - } - - return ((ba_stream_num < - MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) ? true : false); -} - -/* - * This function finds the correct Tx BA stream to delete. - * - * Upon successfully locating, both the TID and the RA are returned. - */ -static inline u8 -mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, - int *ptid, u8 *ra) -{ - int tid; - u8 ret = false; - struct mwifiex_tx_ba_stream_tbl *tx_tbl; - unsigned long flags; - - tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) { - tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user; - *ptid = tx_tbl->tid; - memcpy(ra, tx_tbl->ra, ETH_ALEN); - ret = true; - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - return ret; -} - -/* - * This function checks whether BA stream is set up or not. - */ -static inline int -mwifiex_is_ba_stream_setup(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int tid) -{ - struct mwifiex_tx_ba_stream_tbl *tx_tbl; - - tx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ptr->ra); - if (tx_tbl && IS_BASTREAM_SETUP(tx_tbl)) - return true; - - return false; -} -#endif /* !_MWIFIEX_11N_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/11n_aggr.c b/trunk/drivers/net/wireless/mwifiex/11n_aggr.c deleted file mode 100644 index c9fb0627de43..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/11n_aggr.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n Aggregation - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11n_aggr.h" - -/* - * Creates an AMSDU subframe for aggregation into one AMSDU packet. - * - * The resultant AMSDU subframe format is - - * - * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ - * | DA | SA | Length | SNAP header | MSDU | - * | data[0..5] | data[6..11] | | | data[14..] | - * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ - * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes--> - * - * This function also computes the amount of padding required to make the - * buffer length multiple of 4 bytes. - * - * Data => |DA|SA|SNAP-TYPE|........ .| - * MSDU => |DA|SA|Length|SNAP|...... ..| - */ -static int -mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, - struct sk_buff *skb_src, int *pad) - -{ - int dt_offset; - struct rfc_1042_hdr snap = { - 0xaa, /* LLC DSAP */ - 0xaa, /* LLC SSAP */ - 0x03, /* LLC CTRL */ - {0x00, 0x00, 0x00}, /* SNAP OUI */ - 0x0000 /* SNAP type */ - /* - * This field will be overwritten - * later with ethertype - */ - }; - struct tx_packet_hdr *tx_header = NULL; - - skb_put(skb_aggr, sizeof(*tx_header)); - - tx_header = (struct tx_packet_hdr *) skb_aggr->data; - - /* Copy DA and SA */ - dt_offset = 2 * ETH_ALEN; - memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset); - - /* Copy SNAP header */ - snap.snap_type = *(u16 *) ((u8 *)skb_src->data + dt_offset); - dt_offset += sizeof(u16); - - memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr)); - - skb_pull(skb_src, dt_offset); - - /* Update Length field */ - tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN); - - /* Add payload */ - skb_put(skb_aggr, skb_src->len); - memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data, - skb_src->len); - *pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len + - LLC_SNAP_LEN)) & 3)) : 0; - skb_put(skb_aggr, *pad); - - return skb_aggr->len + *pad; -} - -/* - * Adds TxPD to AMSDU header. - * - * Each AMSDU packet will contain one TxPD at the beginning, - * followed by multiple AMSDU subframes. - */ -static void -mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct txpd *local_tx_pd; - - skb_push(skb, sizeof(*local_tx_pd)); - - local_tx_pd = (struct txpd *) skb->data; - memset(local_tx_pd, 0, sizeof(struct txpd)); - - /* Original priority has been overwritten */ - local_tx_pd->priority = (u8) skb->priority; - local_tx_pd->pkt_delay_2ms = - mwifiex_wmm_compute_drv_pkt_delay(priv, skb); - local_tx_pd->bss_num = priv->bss_num; - local_tx_pd->bss_type = priv->bss_type; - /* Always zero as the data is followed by struct txpd */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); - local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); - local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - - sizeof(*local_tx_pd)); - - if (local_tx_pd->tx_control == 0) - /* TxCtrl set by user or default */ - local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - (priv->adapter->pps_uapsd_mode)) { - if (true == mwifiex_check_last_packet_indication(priv)) { - priv->adapter->tx_lock_flag = true; - local_tx_pd->flags = - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; - } - } -} - -/* - * Counts the number of subframes in an aggregate packet. - * - * This function parses an aggregate packet buffer, looking for - * subframes and counting the number of such subframe found. The - * function automatically skips the DA/SA fields at the beginning - * of each subframe and padding at the end. - */ -static int -mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len) -{ - int pkt_count = 0, pkt_len, pad; - - while (total_pkt_len > 0) { - /* Length will be in network format, change it to host */ - pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN))); - pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? - (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; - data += pkt_len + pad + sizeof(struct ethhdr); - total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); - ++pkt_count; - } - - return pkt_count; -} - -/* - * De-aggregate received packets. - * - * This function parses the received aggregate buffer, extracts each subframe, - * strips off the SNAP header from them and sends the data portion for further - * processing. - * - * Each subframe body is copied onto a separate buffer, which are freed by - * upper layer after processing. The function also performs sanity tests on - * the received buffer. - */ -int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - u16 pkt_len; - int total_pkt_len; - u8 *data; - int pad; - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - struct rxpd *local_rx_pd = (struct rxpd *) skb->data; - struct sk_buff *skb_daggr; - struct mwifiex_rxinfo *rx_info_daggr = NULL; - int ret = -1; - struct rx_packet_hdr *rx_pkt_hdr; - struct mwifiex_adapter *adapter = priv->adapter; - u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; - - data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset); - total_pkt_len = local_rx_pd->rx_pkt_length; - - /* Sanity test */ - if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) { - dev_err(adapter->dev, "total pkt len greater than buffer" - " size %d\n", total_pkt_len); - return -1; - } - - rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len); - - while (total_pkt_len > 0) { - rx_pkt_hdr = (struct rx_packet_hdr *) data; - /* Length will be in network format, change it to host */ - pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN))); - if (pkt_len > total_pkt_len) { - dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n", - total_pkt_len, pkt_len); - break; - } - - pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? - (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; - - total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); - - if (memcmp(&rx_pkt_hdr->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { - memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN); - data += LLC_SNAP_LEN; - pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN; - } else { - *(u16 *) (data + 2 * ETH_ALEN) = (u16) 0; - pkt_len += sizeof(struct ethhdr); - } - - skb_daggr = dev_alloc_skb(pkt_len); - if (!skb_daggr) { - dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n", - __func__); - return -1; - } - rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr); - - rx_info_daggr->bss_index = rx_info->bss_index; - skb_daggr->tstamp = skb->tstamp; - rx_info_daggr->parent = skb; - skb_daggr->priority = skb->priority; - skb_put(skb_daggr, pkt_len); - memcpy(skb_daggr->data, data, pkt_len); - - ret = mwifiex_recv_packet(adapter, skb_daggr); - - switch (ret) { - case -EINPROGRESS: - break; - case -1: - dev_err(adapter->dev, "deaggr: host_to_card failed\n"); - case 0: - mwifiex_recv_packet_complete(adapter, skb_daggr, ret); - break; - default: - break; - } - - data += pkt_len + pad; - } - - return ret; -} - -/* - * Create aggregated packet. - * - * This function creates an aggregated MSDU packet, by combining buffers - * from the RA list. Each individual buffer is encapsulated as an AMSDU - * subframe and all such subframes are concatenated together to form the - * AMSDU packet. - * - * A TxPD is also added to the front of the resultant AMSDU packets for - * transmission. The resultant packets format is - - * - * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+ - * | TxPD |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame| - * | | 1 | 2 | .. | n | - * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+ - */ -int -mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *pra_list, int headroom, - int ptrindex, unsigned long ra_list_flags) - __releases(&priv->wmm.ra_list_spinlock) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct sk_buff *skb_aggr, *skb_src; - struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; - int pad = 0; - int ret = 0; - struct mwifiex_tx_param tx_param; - struct txpd *ptx_pd = NULL; - - if (skb_queue_empty(&pra_list->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return 0; - } - skb_src = skb_peek(&pra_list->skb_head); - tx_info_src = MWIFIEX_SKB_TXCB(skb_src); - skb_aggr = dev_alloc_skb(adapter->tx_buf_size); - if (!skb_aggr) { - dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return -1; - } - skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); - tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); - - tx_info_aggr->bss_index = tx_info_src->bss_index; - skb_aggr->priority = skb_src->priority; - - while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len - + LLC_SNAP_LEN) - <= adapter->tx_buf_size)) { - - if (!skb_queue_empty(&pra_list->skb_head)) - skb_src = skb_dequeue(&pra_list->skb_head); - else - skb_src = NULL; - - pra_list->total_pkts_size -= skb_src->len; - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); - - mwifiex_write_data_complete(adapter, skb_src, 0); - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return -1; - } - - if (!skb_queue_empty(&pra_list->skb_head)) - skb_src = skb_peek(&pra_list->skb_head); - else - skb_src = NULL; - } - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - - /* Last AMSDU packet does not need padding */ - skb_trim(skb_aggr, skb_aggr->len - pad); - - /* Form AMSDU */ - mwifiex_11n_form_amsdu_txpd(priv, skb_aggr); - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - ptx_pd = (struct txpd *)skb_aggr->data; - - skb_push(skb_aggr, headroom); - - tx_param.next_pkt_len = ((pra_list->total_pkts_size) ? - (((pra_list->total_pkts_size) > - adapter->tx_buf_size) ? adapter-> - tx_buf_size : pra_list->total_pkts_size + - LLC_SNAP_LEN + sizeof(struct txpd)) : 0); - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb_aggr->data, - skb_aggr->len, &tx_param); - switch (ret) { - case -EBUSY: - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_write_data_complete(adapter, skb_aggr, -1); - return -1; - } - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - (adapter->pps_uapsd_mode) && - (adapter->tx_lock_flag)) { - priv->adapter->tx_lock_flag = false; - ptx_pd->flags = 0; - } - - skb_queue_tail(&pra_list->skb_head, skb_aggr); - - pra_list->total_pkts_size += skb_aggr->len; - - tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); - break; - case -1: - adapter->data_sent = false; - dev_err(adapter->dev, "%s: host_to_card failed: %#x\n", - __func__, ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb_aggr, ret); - return 0; - case -EINPROGRESS: - adapter->data_sent = false; - break; - case 0: - mwifiex_write_data_complete(adapter, skb_aggr, ret); - break; - default: - break; - } - if (ret != -EBUSY) { - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { - priv->wmm.packets_out[ptrindex]++; - priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list; - } - /* Now bss_prio_cur pointer points to next node */ - adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = - list_first_entry( - &adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_cur->list, - struct mwifiex_bss_prio_node, list); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - } - - return 0; -} diff --git a/trunk/drivers/net/wireless/mwifiex/11n_aggr.h b/trunk/drivers/net/wireless/mwifiex/11n_aggr.h deleted file mode 100644 index 9c6dca7ab02c..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/11n_aggr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n Aggregation - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11N_AGGR_H_ -#define _MWIFIEX_11N_AGGR_H_ - -#define PKT_TYPE_AMSDU 0xE6 - -int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, - struct sk_buff *skb); -int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int headroom, - int ptr_index, unsigned long flags) - __releases(&priv->wmm.ra_list_spinlock); - -#endif /* !_MWIFIEX_11N_AGGR_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c b/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c deleted file mode 100644 index a93c03fdea82..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11n_rxreorder.h" - -/* - * This function dispatches all packets in the Rx reorder table. - * - * There could be holes in the buffer, which are skipped by the function. - * Since the buffer is linear, the function uses rotation to simulate - * circular buffer. - */ -static int -mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl - *rx_reor_tbl_ptr, int start_win) -{ - int no_pkt_to_send, i; - void *rx_tmp_ptr = NULL; - unsigned long flags; - - no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ? - min((start_win - rx_reor_tbl_ptr->start_win), - rx_reor_tbl_ptr->win_size) : rx_reor_tbl_ptr->win_size; - - for (i = 0; i < no_pkt_to_send; ++i) { - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - rx_tmp_ptr = NULL; - if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) { - rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i]; - rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL; - } - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - if (rx_tmp_ptr) - mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); - } - - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - /* - * We don't have a circular buffer, hence use rotation to simulate - * circular buffer - */ - for (i = 0; i < rx_reor_tbl_ptr->win_size - no_pkt_to_send; ++i) { - rx_reor_tbl_ptr->rx_reorder_ptr[i] = - rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i]; - rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = NULL; - } - - rx_reor_tbl_ptr->start_win = start_win; - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - - return 0; -} - -/* - * This function dispatches all packets in the Rx reorder table until - * a hole is found. - * - * The start window is adjusted automatically when a hole is located. - * Since the buffer is linear, the function uses rotation to simulate - * circular buffer. - */ -static int -mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr) -{ - int i, j, xchg; - void *rx_tmp_ptr = NULL; - unsigned long flags; - - for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) { - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) { - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - break; - } - rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i]; - rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL; - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); - } - - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - /* - * We don't have a circular buffer, hence use rotation to simulate - * circular buffer - */ - if (i > 0) { - xchg = rx_reor_tbl_ptr->win_size - i; - for (j = 0; j < xchg; ++j) { - rx_reor_tbl_ptr->rx_reorder_ptr[j] = - rx_reor_tbl_ptr->rx_reorder_ptr[i + j]; - rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = NULL; - } - } - rx_reor_tbl_ptr->start_win = (rx_reor_tbl_ptr->start_win + i) - &(MAX_TID_VALUE - 1); - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - return 0; -} - -/* - * This function deletes the Rx reorder table and frees the memory. - * - * The function stops the associated timer and dispatches all the - * pending packets in the Rx reorder table before deletion. - */ -static void -mwifiex_11n_delete_rx_reorder_tbl_entry(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl - *rx_reor_tbl_ptr) -{ - unsigned long flags; - - if (!rx_reor_tbl_ptr) - return; - - mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, - (rx_reor_tbl_ptr->start_win + - rx_reor_tbl_ptr->win_size) - &(MAX_TID_VALUE - 1)); - - del_timer(&rx_reor_tbl_ptr->timer_context.timer); - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_del(&rx_reor_tbl_ptr->list); - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - kfree(rx_reor_tbl_ptr->rx_reorder_ptr); - kfree(rx_reor_tbl_ptr); -} - -/* - * This function returns the pointer to an entry in Rx reordering - * table which matches the given TA/TID pair. - */ -static struct mwifiex_rx_reorder_tbl * -mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) -{ - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; - unsigned long flags; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) { - if ((!memcmp(rx_reor_tbl_ptr->ta, ta, ETH_ALEN)) - && (rx_reor_tbl_ptr->tid == tid)) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, - flags); - return rx_reor_tbl_ptr; - } - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return NULL; -} - -/* - * This function finds the last sequence number used in the packets - * buffered in Rx reordering table. - */ -static int -mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr) -{ - int i; - - for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) - if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) - return i; - - return -1; -} - -/* - * This function flushes all the packets in Rx reordering table. - * - * The function checks if any packets are currently buffered in the - * table or not. In case there are packets available, it dispatches - * them and then dumps the Rx reordering table. - */ -static void -mwifiex_flush_data(unsigned long context) -{ - struct reorder_tmr_cnxt *reorder_cnxt = - (struct reorder_tmr_cnxt *) context; - int start_win; - - start_win = mwifiex_11n_find_last_seq_num(reorder_cnxt->ptr); - if (start_win >= 0) { - dev_dbg(reorder_cnxt->priv->adapter->dev, - "info: flush data %d\n", start_win); - mwifiex_11n_dispatch_pkt_until_start_win(reorder_cnxt->priv, - reorder_cnxt->ptr, - ((reorder_cnxt->ptr->start_win + - start_win + 1) & (MAX_TID_VALUE - 1))); - } -} - -/* - * This function creates an entry in Rx reordering table for the - * given TA/TID. - * - * The function also initializes the entry with sequence number, window - * size as well as initializes the timer. - * - * If the received TA/TID pair is already present, all the packets are - * dispatched and the window size is moved until the SSN. - */ -static void -mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, - int tid, int win_size, int seq_num) -{ - int i; - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr, *new_node; - u16 last_seq = 0; - unsigned long flags; - - /* - * If we get a TID, ta pair which is already present dispatch all the - * the packets and move the window size until the ssn - */ - rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); - if (rx_reor_tbl_ptr) { - mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, - seq_num); - return; - } - /* if !rx_reor_tbl_ptr then create one */ - new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL); - if (!new_node) { - dev_err(priv->adapter->dev, "%s: failed to alloc new_node\n", - __func__); - return; - } - - INIT_LIST_HEAD(&new_node->list); - new_node->tid = tid; - memcpy(new_node->ta, ta, ETH_ALEN); - new_node->start_win = seq_num; - if (mwifiex_queuing_ra_based(priv)) - /* TODO for adhoc */ - dev_dbg(priv->adapter->dev, - "info: ADHOC:last_seq=%d start_win=%d\n", - last_seq, new_node->start_win); - else - last_seq = priv->rx_seq[tid]; - - if (last_seq >= new_node->start_win) - new_node->start_win = last_seq + 1; - - new_node->win_size = win_size; - - new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, - GFP_KERNEL); - if (!new_node->rx_reorder_ptr) { - kfree((u8 *) new_node); - dev_err(priv->adapter->dev, - "%s: failed to alloc reorder_ptr\n", __func__); - return; - } - - new_node->timer_context.ptr = new_node; - new_node->timer_context.priv = priv; - - init_timer(&new_node->timer_context.timer); - new_node->timer_context.timer.function = mwifiex_flush_data; - new_node->timer_context.timer.data = - (unsigned long) &new_node->timer_context; - - for (i = 0; i < win_size; ++i) - new_node->rx_reorder_ptr[i] = NULL; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr); - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -} - -/* - * This function prepares command for adding a BA request. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting add BA request buffer - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct host_cmd_ds_11n_addba_req *add_ba_req = - (struct host_cmd_ds_11n_addba_req *) - &cmd->params.add_ba_req; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ); - cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN); - memcpy(add_ba_req, data_buf, sizeof(*add_ba_req)); - - return 0; -} - -/* - * This function prepares command for adding a BA response. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting add BA response buffer - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) -{ - struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = - (struct host_cmd_ds_11n_addba_rsp *) - &cmd->params.add_ba_rsp; - struct host_cmd_ds_11n_addba_req *cmd_addba_req = - (struct host_cmd_ds_11n_addba_req *) data_buf; - u8 tid = 0; - int win_size = 0; - uint16_t block_ack_param_set; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); - cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); - - memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr, - ETH_ALEN); - add_ba_rsp->dialog_token = cmd_addba_req->dialog_token; - add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo; - add_ba_rsp->ssn = cmd_addba_req->ssn; - - block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set); - tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); - block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - /* We donot support AMSDU inside AMPDU, hence reset the bit */ - block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; - block_ack_param_set |= (priv->add_ba_param.rx_win_size << - BLOCKACKPARAM_WINSIZE_POS); - add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); - win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) - & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) - >> BLOCKACKPARAM_WINSIZE_POS; - cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set); - - mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr, - tid, win_size, le16_to_cpu(cmd_addba_req->ssn)); - return 0; -} - -/* - * This function prepares command for deleting a BA request. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting del BA request buffer - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct host_cmd_ds_11n_delba *del_ba = (struct host_cmd_ds_11n_delba *) - &cmd->params.del_ba; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA); - cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN); - memcpy(del_ba, data_buf, sizeof(*del_ba)); - - return 0; -} - -/* - * This function identifies if Rx reordering is needed for a received packet. - * - * In case reordering is required, the function will do the reordering - * before sending it to kernel. - * - * The Rx reorder table is checked first with the received TID/TA pair. If - * not found, the received packet is dispatched immediately. But if found, - * the packet is reordered and all the packets in the updated Rx reordering - * table is dispatched until a hole is found. - * - * For sequence number less than the starting window, the packet is dropped. - */ -int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, - u16 seq_num, u16 tid, - u8 *ta, u8 pkt_type, void *payload) -{ - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; - int start_win, end_win, win_size; - int ret = 0; - u16 pkt_index = 0; - - rx_reor_tbl_ptr = - mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv, - tid, ta); - if (!rx_reor_tbl_ptr) { - if (pkt_type != PKT_TYPE_BAR) - mwifiex_process_rx_packet(priv->adapter, payload); - return 0; - } - start_win = rx_reor_tbl_ptr->start_win; - win_size = rx_reor_tbl_ptr->win_size; - end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); - del_timer(&rx_reor_tbl_ptr->timer_context.timer); - mod_timer(&rx_reor_tbl_ptr->timer_context.timer, jiffies - + (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000); - - /* - * If seq_num is less then starting win then ignore and drop the - * packet - */ - if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */ - if (seq_num >= ((start_win + (TWOPOW11)) & (MAX_TID_VALUE - 1)) - && (seq_num < start_win)) - return -1; - } else if ((seq_num < start_win) - || (seq_num > (start_win + (TWOPOW11)))) { - return -1; - } - - /* - * If this packet is a BAR we adjust seq_num as - * WinStart = seq_num - */ - if (pkt_type == PKT_TYPE_BAR) - seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); - - if (((end_win < start_win) - && (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) - && (seq_num > end_win)) || ((end_win > start_win) - && ((seq_num > end_win) || (seq_num < start_win)))) { - end_win = seq_num; - if (((seq_num - win_size) + 1) >= 0) - start_win = (end_win - win_size) + 1; - else - start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; - ret = mwifiex_11n_dispatch_pkt_until_start_win(priv, - rx_reor_tbl_ptr, start_win); - - if (ret) - return ret; - } - - if (pkt_type != PKT_TYPE_BAR) { - if (seq_num >= start_win) - pkt_index = seq_num - start_win; - else - pkt_index = (seq_num+MAX_TID_VALUE) - start_win; - - if (rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index]) - return -1; - - rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index] = payload; - } - - /* - * Dispatch all packets sequentially from start_win until a - * hole is found and adjust the start_win appropriately - */ - ret = mwifiex_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr); - - return ret; -} - -/* - * This function deletes an entry for a given TID/TA pair. - * - * The TID/TA are taken from del BA event body. - */ -void -mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int tid, - u8 *peer_mac, u8 type, int initiator) -{ - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; - struct mwifiex_tx_ba_stream_tbl *ptx_tbl; - u8 cleanup_rx_reorder_tbl; - unsigned long flags; - - if (type == TYPE_DELBA_RECEIVE) - cleanup_rx_reorder_tbl = (initiator) ? true : false; - else - cleanup_rx_reorder_tbl = (initiator) ? false : true; - - dev_dbg(priv->adapter->dev, "event: DELBA: %pM tid=%d, " - "initiator=%d\n", peer_mac, tid, initiator); - - if (cleanup_rx_reorder_tbl) { - rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, - peer_mac); - if (!rx_reor_tbl_ptr) { - dev_dbg(priv->adapter->dev, - "event: TID, TA not found in table\n"); - return; - } - mwifiex_11n_delete_rx_reorder_tbl_entry(priv, rx_reor_tbl_ptr); - } else { - ptx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, peer_mac); - if (!ptx_tbl) { - dev_dbg(priv->adapter->dev, - "event: TID, RA not found in table\n"); - return; - } - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - } -} - -/* - * This function handles the command response of an add BA response. - * - * Handling includes changing the header fields into CPU format and - * creating the stream, provided the add BA is accepted. - */ -int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = - (struct host_cmd_ds_11n_addba_rsp *) - &resp->params.add_ba_rsp; - int tid, win_size; - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr = NULL; - uint16_t block_ack_param_set; - - block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); - - tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - /* - * Check if we had rejected the ADDBA, if yes then do not create - * the stream - */ - if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { - win_size = (block_ack_param_set & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) - >> BLOCKACKPARAM_WINSIZE_POS; - - dev_dbg(priv->adapter->dev, "cmd: ADDBA RSP: %pM" - " tid=%d ssn=%d win_size=%d\n", - add_ba_rsp->peer_mac_addr, - tid, add_ba_rsp->ssn, win_size); - } else { - dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", - add_ba_rsp->peer_mac_addr, tid); - - rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, - tid, add_ba_rsp->peer_mac_addr); - if (rx_reor_tbl_ptr) - mwifiex_11n_delete_rx_reorder_tbl_entry(priv, - rx_reor_tbl_ptr); - } - - return 0; -} - -/* - * This function handles BA stream timeout event by preparing and sending - * a command to the firmware. - */ -void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, - struct host_cmd_ds_11n_batimeout *event) -{ - struct host_cmd_ds_11n_delba delba; - - memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba)); - memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN); - - delba.del_ba_param_set |= - cpu_to_le16((u16) event->tid << DELBA_TID_POS); - delba.del_ba_param_set |= cpu_to_le16( - (u16) event->origninator << DELBA_INITIATOR_POS); - delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); - mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba); -} - -/* - * This function cleans up the Rx reorder table by deleting all the entries - * and re-initializing. - */ -void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) -{ - struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node; - unsigned long flags; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry_safe(del_tbl_ptr, tmp_node, - &priv->rx_reorder_tbl_ptr, list) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - mwifiex_11n_delete_rx_reorder_tbl_entry(priv, del_tbl_ptr); - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); - memset(priv->rx_seq, 0, sizeof(priv->rx_seq)); -} diff --git a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h b/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h deleted file mode 100644 index f3ca8c8c18f9..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11N_RXREORDER_H_ -#define _MWIFIEX_11N_RXREORDER_H_ - -#define MIN_FLUSH_TIMER_MS 50 - -#define PKT_TYPE_BAR 0xE7 -#define MAX_TID_VALUE (2 << 11) -#define TWOPOW11 (2 << 10) - -#define BLOCKACKPARAM_TID_POS 2 -#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1 -#define BLOCKACKPARAM_WINSIZE_POS 6 -#define DELBA_TID_POS 12 -#define DELBA_INITIATOR_POS 11 -#define TYPE_DELBA_SENT 1 -#define TYPE_DELBA_RECEIVE 2 -#define IMMEDIATE_BLOCK_ACK 0x2 - -#define ADDBA_RSP_STATUS_ACCEPT 0 - -int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *, - u16 seqNum, - u16 tid, u8 *ta, - u8 pkttype, void *payload); -void mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int Tid, - u8 *PeerMACAddr, u8 type, - int initiator); -void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, - struct host_cmd_ds_11n_batimeout *event); -int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, - struct host_cmd_ds_command - *resp); -int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, - void *data_buf); -int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, - struct host_cmd_ds_command - *cmd, void *data_buf); -int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, - void *data_buf); -void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv); -struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct - mwifiex_private - *priv, int tid, - u8 *ta); - -#endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/Kconfig b/trunk/drivers/net/wireless/mwifiex/Kconfig deleted file mode 100644 index 86962920cef3..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -config MWIFIEX - tristate "Marvell WiFi-Ex Driver" - depends on CFG80211 - select LIB80211 - ---help--- - This adds support for wireless adapters based on Marvell - 802.11n chipsets. - - If you choose to build it as a module, it will be called - mwifiex. - -config MWIFIEX_SDIO - tristate "Marvell WiFi-Ex Driver for SD8787" - depends on MWIFIEX && MMC - select FW_LOADER - ---help--- - This adds support for wireless adapters based on Marvell - 8787 chipset with SDIO interface. - - If you choose to build it as a module, it will be called - mwifiex_sdio. diff --git a/trunk/drivers/net/wireless/mwifiex/Makefile b/trunk/drivers/net/wireless/mwifiex/Makefile deleted file mode 100644 index 42cb733ea33a..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (C) 2011, Marvell International Ltd. -# -# This software file (the "File") is distributed by Marvell International -# Ltd. under the terms of the GNU General Public License Version 2, June 1991 -# (the "License"). You may use, redistribute and/or modify this File in -# accordance with the terms and conditions of the License, a copy of which -# is available by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -# -# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -# ARE EXPRESSLY DISCLAIMED. The License provides additional details about -# this warranty disclaimer. - - -mwifiex-y += main.o -mwifiex-y += init.o -mwifiex-y += cfp.o -mwifiex-y += cmdevt.o -mwifiex-y += util.o -mwifiex-y += txrx.o -mwifiex-y += wmm.o -mwifiex-y += 11n.o -mwifiex-y += 11n_aggr.o -mwifiex-y += 11n_rxreorder.o -mwifiex-y += scan.o -mwifiex-y += join.o -mwifiex-y += sta_ioctl.o -mwifiex-y += sta_cmd.o -mwifiex-y += sta_cmdresp.o -mwifiex-y += sta_event.o -mwifiex-y += sta_tx.o -mwifiex-y += sta_rx.o -mwifiex-y += cfg80211.o -mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o -obj-$(CONFIG_MWIFIEX) += mwifiex.o - -mwifiex_sdio-y += sdio.o -obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o diff --git a/trunk/drivers/net/wireless/mwifiex/README b/trunk/drivers/net/wireless/mwifiex/README deleted file mode 100644 index b55badef4660..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/README +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (C) 2011, Marvell International Ltd. -# -# This software file (the "File") is distributed by Marvell International -# Ltd. under the terms of the GNU General Public License Version 2, June 1991 -# (the "License"). You may use, redistribute and/or modify this File in -# accordance with the terms and conditions of the License, a copy of which -# is available by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -# -# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -# ARE EXPRESSLY DISCLAIMED. The License provides additional details about -# this warranty disclaimer. - - -=============================================================================== - U S E R M A N U A L - -1) FOR DRIVER INSTALL - - a) Copy sd8787.bin to /lib/firmware/mrvl/ directory, - create the directory if it doesn't exist. - b) Install WLAN driver, - insmod mwifiex.ko - c) Uninstall WLAN driver, - ifconfig mlanX down - rmmod mwifiex - - -2) FOR DRIVER CONFIGURATION AND INFO - The configurations can be done either using the 'iw' user space - utility or debugfs. - - a) 'iw' utility commands - - Following are some useful iw commands:- - -iw dev mlan0 scan - - This command will trigger a scan. - The command will then display the scan table entries - -iw dev mlan0 connect -w [] [] [key 0:abcde d:1123456789a] - The above command can be used to connect to an AP with a particular SSID. - Ap's operating frequency can be specified or even the bssid. If the AP is using - WEP encryption, wep keys can be specified in the command. - Note: Every time before connecting to an AP scan command (iw dev mlan0 scan) should be used by user. - -iw dev mlan0 disconnect - This command will be used to disconnect from an AP. - - -iw dev mlan0 ibss join [fixed-freq] [fixed-bssid] [key 0:abcde] - The command will be used to join or create an ibss. Optionally, operating frequency, - bssid and the security related parameters can be specified while joining/creating - and ibss. - -iw dev mlan0 ibss leave - The command will be used to leave an ibss network. - -iw dev mlan0 link - The command will be used to get the connection status. The command will return parameters - such as SSID, operating frequency, rx/tx packets, signal strength, tx bitrate. - - Apart from the iw utility all standard configurations using the 'iwconfig' utility are also supported. - - b) Debugfs interface - - The debugfs interface can be used for configurations and for getting - some useful information from the driver. - The section below explains the configurations that can be - done. - - Mount debugfs to /debugfs mount point: - - mkdir /debugfs - mount -t debugfs debugfs /debugfs - - The information is provided in /debugfs/mwifiex/mlanX/: - -iw reg set - The command will be used to change the regulatory domain. - -iw reg get - The command will be used to get current regulatory domain. - -info - This command is used to get driver info. - - Usage: - cat info - - driver_name = "mwifiex" - driver_version = - interface_name = "mlanX" - bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" - media_state = "Disconnected" | "Connected" - mac_address = <6-byte adapter MAC address> - multicase_count = - essid = - bssid = - channel = - region_code = - multicasr_address[n] = - num_tx_bytes = - num_rx_bytes = - num_tx_pkts = - num_rx_pkts = - num_tx_pkts_dropped = - num_rx_pkts_dropped = - num_tx_pkts_err = - num_rx_pkts_err = - carrier "on" | "off" - tx queue "stopped" | "started" - - The following debug info are provided in /debugfs/mwifiex/mlanX/debug: - - int_counter = - wmm_ac_vo = - wmm_ac_vi = - wmm_ac_be = - wmm_ac_bk = - max_tx_buf_size = - tx_buf_size = - curr_tx_buf_size = - ps_mode = <0/1, CAM mode/PS mode> - ps_state = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state> - is_deep_sleep = <0/1, not deep sleep state/deep sleep state> - wakeup_dev_req = <0/1, wakeup device not required/required> - wakeup_tries = - hs_configured = <0/1, host sleep not configured/configured> - hs_activated = <0/1, extended host sleep not activated/activated> - num_tx_timeout = - num_cmd_timeout = - timeout_cmd_id = - timeout_cmd_act = - last_cmd_id = - last_cmd_act = - last_cmd_index = <0 based last command index> - last_cmd_resp_id = - last_cmd_resp_index = <0 based last command response index> - last_event = - last_event_index = <0 based last event index> - num_cmd_h2c_fail = - num_cmd_sleep_cfm_fail = - num_tx_h2c_fail = - num_evt_deauth = - num_evt_disassoc = - num_evt_link_lost = - num_cmd_deauth = - num_cmd_assoc_ok = - num_cmd_assoc_fail = - cmd_sent = <0/1, send command resources available/sending command to device> - data_sent = <0/1, send data resources available/sending data to device> - mp_rd_bitmap = - mp_wr_bitmap = - cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> - event_received = <0/1, no event to process/event received and yet to process> - cmd_pending = - tx_pending = - rx_pending = - - -3) FOR DRIVER CONFIGURATION - -regrdwr - This command is used to read/write the adapter register. - - Usage: - echo " [value]" > regrdwr - cat regrdwr - - where the parameters are, - : 1:MAC/SOC, 2:BBP, 3:RF, 4:PMIC, 5:CAU - : offset of register - [value]: value to be written - - Examples: - echo "1 0xa060" > regrdwr : Read the MAC register - echo "1 0xa060 0x12" > regrdwr : Write the MAC register - echo "1 0xa794 0x80000000" > regrdwr - : Write 0x80000000 to MAC register -rdeeprom - This command is used to read the EEPROM contents of the card. - - Usage: - echo " " > rdeeprom - cat rdeeprom - - where the parameters are, - : multiples of 4 - : 4-20, multiples of 4 - - Example: - echo "0 20" > rdeeprom : Read 20 bytes of EEPROM data from offset 0 - -getlog - This command is used to get the statistics available in the station. - Usage: - - cat getlog - -=============================================================================== diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c deleted file mode 100644 index 98009e2194c5..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ /dev/null @@ -1,1421 +0,0 @@ -/* - * Marvell Wireless LAN device driver: CFG80211 - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "cfg80211.h" -#include "main.h" - -/* - * This function maps the nl802.11 channel type into driver channel type. - * - * The mapping is as follows - - * NL80211_CHAN_NO_HT -> NO_SEC_CHANNEL - * NL80211_CHAN_HT20 -> NO_SEC_CHANNEL - * NL80211_CHAN_HT40PLUS -> SEC_CHANNEL_ABOVE - * NL80211_CHAN_HT40MINUS -> SEC_CHANNEL_BELOW - * Others -> NO_SEC_CHANNEL - */ -static int -mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type - channel_type) -{ - switch (channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - return NO_SEC_CHANNEL; - case NL80211_CHAN_HT40PLUS: - return SEC_CHANNEL_ABOVE; - case NL80211_CHAN_HT40MINUS: - return SEC_CHANNEL_BELOW; - default: - return NO_SEC_CHANNEL; - } -} - -/* - * This function maps the driver channel type into nl802.11 channel type. - * - * The mapping is as follows - - * NO_SEC_CHANNEL -> NL80211_CHAN_HT20 - * SEC_CHANNEL_ABOVE -> NL80211_CHAN_HT40PLUS - * SEC_CHANNEL_BELOW -> NL80211_CHAN_HT40MINUS - * Others -> NL80211_CHAN_HT20 - */ -static enum nl80211_channel_type -mwifiex_channels_to_cfg80211_channel_type(int channel_type) -{ - switch (channel_type) { - case NO_SEC_CHANNEL: - return NL80211_CHAN_HT20; - case SEC_CHANNEL_ABOVE: - return NL80211_CHAN_HT40PLUS; - case SEC_CHANNEL_BELOW: - return NL80211_CHAN_HT40MINUS; - default: - return NL80211_CHAN_HT20; - } -} - -/* - * This function checks whether WEP is set. - */ -static int -mwifiex_is_alg_wep(u32 cipher) -{ - int alg = 0; - - switch (cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - alg = 1; - break; - default: - alg = 0; - break; - } - return alg; -} - -/* - * This function retrieves the private structure from kernel wiphy structure. - */ -static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy) -{ - return (void *) (*(unsigned long *) wiphy_priv(wiphy)); -} - -/* - * CFG802.11 operation handler to delete a network key. - */ -static int -mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, bool pairwise, const u8 *mac_addr) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { - wiphy_err(wiphy, "deleting the crypto keys\n"); - return -EFAULT; - } - - wiphy_dbg(wiphy, "info: crypto keys deleted\n"); - return 0; -} - -/* - * CFG802.11 operation handler to set Tx power. - */ -static int -mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, - enum nl80211_tx_power_setting type, - int dbm) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - struct mwifiex_power_cfg power_cfg; - - if (type == NL80211_TX_POWER_FIXED) { - power_cfg.is_power_auto = 0; - power_cfg.power_level = dbm; - } else { - power_cfg.is_power_auto = 1; - } - - return mwifiex_set_tx_power(priv, &power_cfg); -} - -/* - * CFG802.11 operation handler to set Power Save option. - * - * The timeout value, if provided, is currently ignored. - */ -static int -mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, - struct net_device *dev, - bool enabled, int timeout) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - u32 ps_mode; - - if (timeout) - wiphy_dbg(wiphy, - "info: ignoring the timeout value" - " for IEEE power save\n"); - - ps_mode = enabled; - - return mwifiex_drv_set_power(priv, &ps_mode); -} - -/* - * CFG802.11 operation handler to set the default network key. - */ -static int -mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, bool unicast, - bool multicast) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - /* Return if WEP key not configured */ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED) - return 0; - - if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { - wiphy_err(wiphy, "set default Tx key index\n"); - return -EFAULT; - } - - return 0; -} - -/* - * CFG802.11 operation handler to add a network key. - */ -static int -mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, bool pairwise, const u8 *mac_addr, - struct key_params *params) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - if (mwifiex_set_encode(priv, params->key, params->key_len, - key_index, 0)) { - wiphy_err(wiphy, "crypto keys added\n"); - return -EFAULT; - } - - return 0; -} - -/* - * This function sends domain information to the firmware. - * - * The following information are passed to the firmware - - * - Country codes - * - Sub bands (first channel, number of channels, maximum Tx power) - */ -static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) -{ - u8 no_of_triplet = 0; - struct ieee80211_country_ie_triplet *t; - u8 no_of_parsed_chan = 0; - u8 first_chan = 0, next_chan = 0, max_pwr = 0; - u8 i, flag = 0; - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; - - /* Set country code */ - domain_info->country_code[0] = priv->country_code[0]; - domain_info->country_code[1] = priv->country_code[1]; - domain_info->country_code[2] = ' '; - - band = mwifiex_band_to_radio_type(adapter->config_bands); - if (!wiphy->bands[band]) { - wiphy_err(wiphy, "11D: setting domain info in FW\n"); - return -1; - } - - sband = wiphy->bands[band]; - - for (i = 0; i < sband->n_channels ; i++) { - ch = &sband->channels[i]; - if (ch->flags & IEEE80211_CHAN_DISABLED) - continue; - - if (!flag) { - flag = 1; - first_chan = (u32) ch->hw_value; - next_chan = first_chan; - max_pwr = ch->max_power; - no_of_parsed_chan = 1; - continue; - } - - if (ch->hw_value == next_chan + 1 && - ch->max_power == max_pwr) { - next_chan++; - no_of_parsed_chan++; - } else { - t = &domain_info->triplet[no_of_triplet]; - t->chans.first_channel = first_chan; - t->chans.num_channels = no_of_parsed_chan; - t->chans.max_power = max_pwr; - no_of_triplet++; - first_chan = (u32) ch->hw_value; - next_chan = first_chan; - max_pwr = ch->max_power; - no_of_parsed_chan = 1; - } - } - - if (flag) { - t = &domain_info->triplet[no_of_triplet]; - t->chans.first_channel = first_chan; - t->chans.num_channels = no_of_parsed_chan; - t->chans.max_power = max_pwr; - no_of_triplet++; - } - - domain_info->no_of_triplet = no_of_triplet; - - if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, - HostCmd_ACT_GEN_SET, 0, NULL)) { - wiphy_err(wiphy, "11D: setting domain info in FW\n"); - return -1; - } - - return 0; -} - -/* - * CFG802.11 regulatory domain callback function. - * - * This function is called when the regulatory domain is changed due to the - * following reasons - - * - Set by driver - * - Set by system core - * - Set by user - * - Set bt Country IE - */ -static int mwifiex_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain" - " %c%c\n", request->alpha2[0], request->alpha2[1]); - - memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); - - switch (request->initiator) { - case NL80211_REGDOM_SET_BY_DRIVER: - case NL80211_REGDOM_SET_BY_CORE: - case NL80211_REGDOM_SET_BY_USER: - break; - /* Todo: apply driver specific changes in channel flags based - on the request initiator if necessary. */ - case NL80211_REGDOM_SET_BY_COUNTRY_IE: - break; - } - mwifiex_send_domain_info_cmd_fw(wiphy); - - return 0; -} - -/* - * This function sets the RF channel. - * - * This function creates multiple IOCTL requests, populates them accordingly - * and issues them to set the band/channel and frequency. - */ -static int -mwifiex_set_rf_channel(struct mwifiex_private *priv, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - struct mwifiex_chan_freq_power cfp; - struct mwifiex_ds_band_cfg band_cfg; - u32 config_bands = 0; - struct wiphy *wiphy = priv->wdev->wiphy; - - if (chan) { - memset(&band_cfg, 0, sizeof(band_cfg)); - /* Set appropriate bands */ - if (chan->band == IEEE80211_BAND_2GHZ) - config_bands = BAND_B | BAND_G | BAND_GN; - else - config_bands = BAND_AN | BAND_A; - if (priv->bss_mode == NL80211_IFTYPE_STATION - || priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) { - band_cfg.config_bands = config_bands; - } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - band_cfg.config_bands = config_bands; - band_cfg.adhoc_start_band = config_bands; - } - - band_cfg.sec_chan_offset = - mwifiex_cfg80211_channel_type_to_mwifiex_channels - (channel_type); - - if (mwifiex_set_radio_band_cfg(priv, &band_cfg)) - return -EFAULT; - - mwifiex_send_domain_info_cmd_fw(wiphy); - } - - wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and " - "mode %d\n", config_bands, band_cfg.sec_chan_offset, - priv->bss_mode); - if (!chan) - return 0; - - memset(&cfp, 0, sizeof(cfp)); - cfp.freq = chan->center_freq; - cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); - - if (mwifiex_bss_set_channel(priv, &cfp)) - return -EFAULT; - - return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); -} - -/* - * CFG802.11 operation handler to set channel. - * - * This function can only be used when station is not connected. - */ -static int -mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - if (priv->media_connected) { - wiphy_err(wiphy, "This setting is valid only when station " - "is not connected\n"); - return -EINVAL; - } - - return mwifiex_set_rf_channel(priv, chan, channel_type); -} - -/* - * This function sets the fragmentation threshold. - * - * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE - * and MWIFIEX_FRAG_MAX_VALUE. - */ -static int -mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) -{ - int ret = 0; - - if (frag_thr < MWIFIEX_FRAG_MIN_VALUE - || frag_thr > MWIFIEX_FRAG_MAX_VALUE) - return -EINVAL; - - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, FRAG_THRESH_I, - &frag_thr); - - return ret; -} - -/* - * This function sets the RTS threshold. - - * The rts value must lie between MWIFIEX_RTS_MIN_VALUE - * and MWIFIEX_RTS_MAX_VALUE. - */ -static int -mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) -{ - if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) - rts_thr = MWIFIEX_RTS_MAX_VALUE; - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, RTS_THRESH_I, - &rts_thr); -} - -/* - * CFG802.11 operation handler to set wiphy parameters. - * - * This function can be used to set the RTS threshold and the - * Fragmentation threshold of the driver. - */ -static int -mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - int ret = 0; - - if (changed & WIPHY_PARAM_RTS_THRESHOLD) { - ret = mwifiex_set_rts(priv, wiphy->rts_threshold); - if (ret) - return ret; - } - - if (changed & WIPHY_PARAM_FRAG_THRESHOLD) - ret = mwifiex_set_frag(priv, wiphy->frag_threshold); - - return ret; -} - -/* - * CFG802.11 operation handler to change interface type. - */ -static int -mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - int ret = 0; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (priv->bss_mode == type) { - wiphy_warn(wiphy, "already set to required type\n"); - return 0; - } - - priv->bss_mode = type; - - switch (type) { - case NL80211_IFTYPE_ADHOC: - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; - wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); - break; - case NL80211_IFTYPE_STATION: - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - wiphy_dbg(wiphy, "info: setting interface type to managed\n"); - break; - case NL80211_IFTYPE_UNSPECIFIED: - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - wiphy_dbg(wiphy, "info: setting interface type to auto\n"); - return 0; - default: - wiphy_err(wiphy, "unknown interface type: %d\n", type); - return -EINVAL; - } - - mwifiex_deauthenticate(priv, NULL); - - priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL); - - return ret; -} - -/* - * This function dumps the station information on a buffer. - * - * The following information are shown - - * - Total bytes transmitted - * - Total bytes received - * - Total packets transmitted - * - Total packets received - * - Signal quality level - * - Transmission rate - */ -static int -mwifiex_dump_station_info(struct mwifiex_private *priv, - struct station_info *sinfo) -{ - struct mwifiex_ds_get_signal signal; - struct mwifiex_rate_cfg rate; - int ret = 0; - - sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | - STATION_INFO_RX_PACKETS | - STATION_INFO_TX_PACKETS - | STATION_INFO_SIGNAL | STATION_INFO_TX_BITRATE; - - /* Get signal information from the firmware */ - memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal)); - if (mwifiex_get_signal_info(priv, &signal)) { - dev_err(priv->adapter->dev, "getting signal information\n"); - ret = -EFAULT; - } - - if (mwifiex_drv_get_data_rate(priv, &rate)) { - dev_err(priv->adapter->dev, "getting data rate\n"); - ret = -EFAULT; - } - - sinfo->rx_bytes = priv->stats.rx_bytes; - sinfo->tx_bytes = priv->stats.tx_bytes; - sinfo->rx_packets = priv->stats.rx_packets; - sinfo->tx_packets = priv->stats.tx_packets; - sinfo->signal = priv->w_stats.qual.level; - sinfo->txrate.legacy = rate.rate; - - return ret; -} - -/* - * CFG802.11 operation handler to get station information. - * - * This function only works in connected mode, and dumps the - * requested station information, if available. - */ -static int -mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_info *sinfo) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - mwifiex_dump_station_info(priv, sinfo); - - if (!priv->media_connected) - return -ENOENT; - if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) - return -ENOENT; - - return mwifiex_dump_station_info(priv, sinfo); -} - -/* Supported rates to be advertised to the cfg80211 */ - -static struct ieee80211_rate mwifiex_rates[] = { - {.bitrate = 10, .hw_value = 2, }, - {.bitrate = 20, .hw_value = 4, }, - {.bitrate = 55, .hw_value = 11, }, - {.bitrate = 110, .hw_value = 22, }, - {.bitrate = 220, .hw_value = 44, }, - {.bitrate = 60, .hw_value = 12, }, - {.bitrate = 90, .hw_value = 18, }, - {.bitrate = 120, .hw_value = 24, }, - {.bitrate = 180, .hw_value = 36, }, - {.bitrate = 240, .hw_value = 48, }, - {.bitrate = 360, .hw_value = 72, }, - {.bitrate = 480, .hw_value = 96, }, - {.bitrate = 540, .hw_value = 108, }, - {.bitrate = 720, .hw_value = 144, }, -}; - -/* Channel definitions to be advertised to cfg80211 */ - -static struct ieee80211_channel mwifiex_channels_2ghz[] = { - {.center_freq = 2412, .hw_value = 1, }, - {.center_freq = 2417, .hw_value = 2, }, - {.center_freq = 2422, .hw_value = 3, }, - {.center_freq = 2427, .hw_value = 4, }, - {.center_freq = 2432, .hw_value = 5, }, - {.center_freq = 2437, .hw_value = 6, }, - {.center_freq = 2442, .hw_value = 7, }, - {.center_freq = 2447, .hw_value = 8, }, - {.center_freq = 2452, .hw_value = 9, }, - {.center_freq = 2457, .hw_value = 10, }, - {.center_freq = 2462, .hw_value = 11, }, - {.center_freq = 2467, .hw_value = 12, }, - {.center_freq = 2472, .hw_value = 13, }, - {.center_freq = 2484, .hw_value = 14, }, -}; - -static struct ieee80211_supported_band mwifiex_band_2ghz = { - .channels = mwifiex_channels_2ghz, - .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz), - .bitrates = mwifiex_rates, - .n_bitrates = 14, -}; - -static struct ieee80211_channel mwifiex_channels_5ghz[] = { - {.center_freq = 5040, .hw_value = 8, }, - {.center_freq = 5060, .hw_value = 12, }, - {.center_freq = 5080, .hw_value = 16, }, - {.center_freq = 5170, .hw_value = 34, }, - {.center_freq = 5190, .hw_value = 38, }, - {.center_freq = 5210, .hw_value = 42, }, - {.center_freq = 5230, .hw_value = 46, }, - {.center_freq = 5180, .hw_value = 36, }, - {.center_freq = 5200, .hw_value = 40, }, - {.center_freq = 5220, .hw_value = 44, }, - {.center_freq = 5240, .hw_value = 48, }, - {.center_freq = 5260, .hw_value = 52, }, - {.center_freq = 5280, .hw_value = 56, }, - {.center_freq = 5300, .hw_value = 60, }, - {.center_freq = 5320, .hw_value = 64, }, - {.center_freq = 5500, .hw_value = 100, }, - {.center_freq = 5520, .hw_value = 104, }, - {.center_freq = 5540, .hw_value = 108, }, - {.center_freq = 5560, .hw_value = 112, }, - {.center_freq = 5580, .hw_value = 116, }, - {.center_freq = 5600, .hw_value = 120, }, - {.center_freq = 5620, .hw_value = 124, }, - {.center_freq = 5640, .hw_value = 128, }, - {.center_freq = 5660, .hw_value = 132, }, - {.center_freq = 5680, .hw_value = 136, }, - {.center_freq = 5700, .hw_value = 140, }, - {.center_freq = 5745, .hw_value = 149, }, - {.center_freq = 5765, .hw_value = 153, }, - {.center_freq = 5785, .hw_value = 157, }, - {.center_freq = 5805, .hw_value = 161, }, - {.center_freq = 5825, .hw_value = 165, }, -}; - -static struct ieee80211_supported_band mwifiex_band_5ghz = { - .channels = mwifiex_channels_5ghz, - .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz), - .bitrates = mwifiex_rates - 4, - .n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4, -}; - - -/* Supported crypto cipher suits to be advertised to cfg80211 */ - -static const u32 mwifiex_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, -}; - -/* - * CFG802.11 operation handler for disconnection request. - * - * This function does not work when there is already a disconnection - * procedure going on. - */ -static int -mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (priv->disconnect) - return -EBUSY; - - priv->disconnect = 1; - if (mwifiex_deauthenticate(priv, NULL)) - return -EFAULT; - - wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" - " reason code %d\n", priv->cfg_bssid, reason_code); - - queue_work(priv->workqueue, &priv->cfg_workqueue); - - return 0; -} - -/* - * This function informs the CFG802.11 subsystem of a new IBSS. - * - * The following information are sent to the CFG802.11 subsystem - * to register the new IBSS. If we do not register the new IBSS, - * a kernel panic will result. - * - SSID - * - SSID length - * - BSSID - * - Channel - */ -static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) -{ - struct ieee80211_channel *chan; - struct mwifiex_bss_info bss_info; - int ie_len = 0; - u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; - - if (mwifiex_get_bss_info(priv, &bss_info)) - return -1; - - ie_buf[0] = WLAN_EID_SSID; - ie_buf[1] = bss_info.ssid.ssid_len; - - memcpy(&ie_buf[sizeof(struct ieee_types_header)], - &bss_info.ssid.ssid, - bss_info.ssid.ssid_len); - ie_len = ie_buf[1] + sizeof(struct ieee_types_header); - - chan = __ieee80211_get_channel(priv->wdev->wiphy, - ieee80211_channel_to_frequency(bss_info.bss_chan, - priv->curr_bss_params.band)); - - cfg80211_inform_bss(priv->wdev->wiphy, chan, - bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, - 0, ie_buf, ie_len, 0, GFP_KERNEL); - memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); - - return 0; -} - -/* - * This function informs the CFG802.11 subsystem of a new BSS connection. - * - * The following information are sent to the CFG802.11 subsystem - * to register the new BSS connection. If we do not register the new BSS, - * a kernel panic will result. - * - MAC address - * - Capabilities - * - Beacon period - * - RSSI value - * - Channel - * - Supported rates IE - * - Extended capabilities IE - * - DS parameter set IE - * - HT Capability IE - * - Vendor Specific IE (221) - * - WPA IE - * - RSN IE - */ -static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *ssid) -{ - struct mwifiex_scan_resp scan_resp; - struct mwifiex_bssdescriptor *scan_table; - int i, j; - struct ieee80211_channel *chan; - u8 *ie, *ie_buf; - u32 ie_len; - u8 *beacon; - int beacon_size; - u8 element_id, element_len; - - memset(&scan_resp, 0, sizeof(scan_resp)); - scan_resp.scan_table = (u8 *) priv->adapter->scan_table; - scan_resp.num_in_scan_table = priv->adapter->num_in_scan_table; - -#define MAX_IE_BUF 2048 - ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); - if (!ie_buf) { - dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n", - __func__); - return -ENOMEM; - } - - scan_table = (struct mwifiex_bssdescriptor *) scan_resp.scan_table; - for (i = 0; i < scan_resp.num_in_scan_table; i++) { - if (ssid) { - /* Inform specific BSS only */ - if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, - ssid->ssid_len)) - continue; - } - memset(ie_buf, 0, MAX_IE_BUF); - ie_buf[0] = WLAN_EID_SSID; - ie_buf[1] = scan_table[i].ssid.ssid_len; - memcpy(&ie_buf[sizeof(struct ieee_types_header)], - scan_table[i].ssid.ssid, ie_buf[1]); - - ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header); - ie_len = ie_buf[1] + sizeof(struct ieee_types_header); - - ie[0] = WLAN_EID_SUPP_RATES; - - for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) { - if (!scan_table[i].supported_rates[j]) - break; - else - ie[j + sizeof(struct ieee_types_header)] = - scan_table[i].supported_rates[j]; - } - - ie[1] = j; - ie_len += ie[1] + sizeof(struct ieee_types_header); - - beacon = scan_table[i].beacon_buf; - beacon_size = scan_table[i].beacon_buf_size; - - /* Skip time stamp, beacon interval and capability */ - - if (beacon) { - beacon += sizeof(scan_table[i].beacon_period) - + sizeof(scan_table[i].time_stamp) + - +sizeof(scan_table[i].cap_info_bitmap); - - beacon_size -= sizeof(scan_table[i].beacon_period) - + sizeof(scan_table[i].time_stamp) - + sizeof(scan_table[i].cap_info_bitmap); - } - - while (beacon_size >= sizeof(struct ieee_types_header)) { - ie = ie_buf + ie_len; - element_id = *beacon; - element_len = *(beacon + 1); - if (beacon_size < (int) element_len + - sizeof(struct ieee_types_header)) { - dev_err(priv->adapter->dev, "%s: in processing" - " IE, bytes left < IE length\n", - __func__); - break; - } - switch (element_id) { - case WLAN_EID_EXT_CAPABILITY: - case WLAN_EID_DS_PARAMS: - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_VENDOR_SPECIFIC: - case WLAN_EID_RSN: - case WLAN_EID_BSS_AC_ACCESS_DELAY: - ie[0] = element_id; - ie[1] = element_len; - memcpy(&ie[sizeof(struct ieee_types_header)], - (u8 *) beacon - + sizeof(struct ieee_types_header), - element_len); - ie_len += ie[1] + - sizeof(struct ieee_types_header); - break; - default: - break; - } - beacon += element_len + - sizeof(struct ieee_types_header); - beacon_size -= element_len + - sizeof(struct ieee_types_header); - } - chan = ieee80211_get_channel(priv->wdev->wiphy, - scan_table[i].freq); - cfg80211_inform_bss(priv->wdev->wiphy, chan, - scan_table[i].mac_address, - 0, scan_table[i].cap_info_bitmap, - scan_table[i].beacon_period, - ie_buf, ie_len, - scan_table[i].rssi, GFP_KERNEL); - } - - kfree(ie_buf); - return 0; -} - -/* - * This function connects with a BSS. - * - * This function handles both Infra and Ad-Hoc modes. It also performs - * validity checking on the provided parameters, disconnects from the - * current BSS (if any), sets up the association/scan parameters, - * including security settings, and performs specific SSID scan before - * trying to connect. - * - * For Infra mode, the function returns failure if the specified SSID - * is not found in scan table. However, for Ad-Hoc mode, it can create - * the IBSS if it does not exist. On successful completion in either case, - * the function notifies the CFG802.11 subsystem of the new BSS connection, - * otherwise the kernel will panic. - */ -static int -mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, - u8 *bssid, int mode, struct ieee80211_channel *channel, - struct cfg80211_connect_params *sme, bool privacy) -{ - struct mwifiex_802_11_ssid req_ssid; - struct mwifiex_ssid_bssid ssid_bssid; - int ret = 0; - int auth_type = 0; - - memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); - memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); - - req_ssid.ssid_len = ssid_len; - if (ssid_len > IEEE80211_MAX_SSID_LEN) { - dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); - return -EINVAL; - } - - memcpy(req_ssid.ssid, ssid, ssid_len); - if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) { - dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); - return -EINVAL; - } - - /* disconnect before try to associate */ - mwifiex_deauthenticate(priv, NULL); - - if (channel) - ret = mwifiex_set_rf_channel(priv, channel, - mwifiex_channels_to_cfg80211_channel_type - (priv->adapter->chan_offset)); - - ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ - - if (mode == NL80211_IFTYPE_ADHOC) { - /* "privacy" is set only for ad-hoc mode */ - if (privacy) { - /* - * Keep WLAN_CIPHER_SUITE_WEP104 for now so that - * the firmware can find a matching network from the - * scan. The cfg80211 does not give us the encryption - * mode at this stage so just setting it to WEP here. - */ - priv->sec_info.encryption_mode = - WLAN_CIPHER_SUITE_WEP104; - priv->sec_info.authentication_mode = - NL80211_AUTHTYPE_OPEN_SYSTEM; - } - - goto done; - } - - /* Now handle infra mode. "sme" is valid for infra mode only */ - if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC - || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) - auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) - auth_type = NL80211_AUTHTYPE_SHARED_KEY; - - if (sme->crypto.n_ciphers_pairwise) { - priv->sec_info.encryption_mode = - sme->crypto.ciphers_pairwise[0]; - priv->sec_info.authentication_mode = auth_type; - } - - if (sme->crypto.cipher_group) { - priv->sec_info.encryption_mode = sme->crypto.cipher_group; - priv->sec_info.authentication_mode = auth_type; - } - if (sme->ie) - ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); - - if (sme->key) { - if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) { - dev_dbg(priv->adapter->dev, - "info: setting wep encryption" - " with key len %d\n", sme->key_len); - ret = mwifiex_set_encode(priv, sme->key, sme->key_len, - sme->key_idx, 0); - } - } -done: - /* Do specific SSID scanning */ - if (mwifiex_request_scan(priv, &req_ssid)) { - dev_err(priv->adapter->dev, "scan error\n"); - return -EFAULT; - } - - - memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); - - if (mode != NL80211_IFTYPE_ADHOC) { - if (mwifiex_find_best_bss(priv, &ssid_bssid)) - return -EFAULT; - /* Inform the BSS information to kernel, otherwise - * kernel will give a panic after successful assoc */ - if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) - return -EFAULT; - } - - dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", - (char *) req_ssid.ssid, ssid_bssid.bssid); - - memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6); - - /* Connect to BSS by ESSID */ - memset(&ssid_bssid.bssid, 0, ETH_ALEN); - - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - - if (mwifiex_bss_start(priv, &ssid_bssid)) - return -EFAULT; - - if (mode == NL80211_IFTYPE_ADHOC) { - /* Inform the BSS information to kernel, otherwise - * kernel will give a panic after successful assoc */ - if (mwifiex_cfg80211_inform_ibss_bss(priv)) - return -EFAULT; - } - - return ret; -} - -/* - * CFG802.11 operation handler for association request. - * - * This function does not work when the current mode is set to Ad-Hoc, or - * when there is already an association procedure going on. The given BSS - * information is used to associate. - */ -static int -mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int ret = 0; - - if (priv->assoc_request) - return -EBUSY; - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - wiphy_err(wiphy, "received infra assoc request " - "when station is in ibss mode\n"); - goto done; - } - - priv->assoc_request = 1; - - wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", - (char *) sme->ssid, sme->bssid); - - ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, - priv->bss_mode, sme->channel, sme, 0); - -done: - priv->assoc_result = ret; - queue_work(priv->workqueue, &priv->cfg_workqueue); - return ret; -} - -/* - * CFG802.11 operation handler to join an IBSS. - * - * This function does not work in any mode other than Ad-Hoc, or if - * a join operation is already in progress. - */ -static int -mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - int ret = 0; - - if (priv->ibss_join_request) - return -EBUSY; - - if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { - wiphy_err(wiphy, "request to join ibss received " - "when station is not in ibss mode\n"); - goto done; - } - - priv->ibss_join_request = 1; - - wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", - (char *) params->ssid, params->bssid); - - ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, - params->bssid, priv->bss_mode, - params->channel, NULL, params->privacy); -done: - priv->ibss_join_result = ret; - queue_work(priv->workqueue, &priv->cfg_workqueue); - return ret; -} - -/* - * CFG802.11 operation handler to leave an IBSS. - * - * This function does not work if a leave operation is - * already in progress. - */ -static int -mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - if (priv->disconnect) - return -EBUSY; - - priv->disconnect = 1; - - wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", - priv->cfg_bssid); - if (mwifiex_deauthenticate(priv, NULL)) - return -EFAULT; - - queue_work(priv->workqueue, &priv->cfg_workqueue); - - return 0; -} - -/* - * CFG802.11 operation handler for scan request. - * - * This function issues a scan request to the firmware based upon - * the user specified scan configuration. On successfull completion, - * it also informs the results. - */ -static int -mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); - - if (priv->scan_request && priv->scan_request != request) - return -EBUSY; - - priv->scan_request = request; - - queue_work(priv->workqueue, &priv->cfg_workqueue); - return 0; -} - -/* - * This function sets up the CFG802.11 specific HT capability fields - * with default values. - * - * The following default values are set - - * - HT Supported = True - * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K - * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE - * - HT Capabilities supported by firmware - * - MCS information, Rx mask = 0xff - * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) - */ -static void -mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, - struct mwifiex_private *priv) -{ - int rx_mcs_supp; - struct ieee80211_mcs_info mcs_set; - u8 *mcs = (u8 *)&mcs_set; - struct mwifiex_adapter *adapter = priv->adapter; - - ht_info->ht_supported = true; - ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; - - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - - /* Fill HT capability information */ - if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - else - ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - - if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_SGI_20; - else - ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20; - - if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_SGI_40; - else - ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; - - if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; - else - ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - - if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; - else - ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; - - ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; - ht_info->cap |= IEEE80211_HT_CAP_SM_PS; - - rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); - /* Set MCS for 1x1 */ - memset(mcs, 0xff, rx_mcs_supp); - /* Clear all the other values */ - memset(&mcs[rx_mcs_supp], 0, - sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); - if (priv->bss_mode == NL80211_IFTYPE_STATION || - ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) - /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ - SETHT_MCS32(mcs_set.rx_mask); - - memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info)); - - ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; -} - -/* station cfg80211 operations */ -static struct cfg80211_ops mwifiex_cfg80211_ops = { - .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, - .scan = mwifiex_cfg80211_scan, - .connect = mwifiex_cfg80211_connect, - .disconnect = mwifiex_cfg80211_disconnect, - .get_station = mwifiex_cfg80211_get_station, - .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, - .set_channel = mwifiex_cfg80211_set_channel, - .join_ibss = mwifiex_cfg80211_join_ibss, - .leave_ibss = mwifiex_cfg80211_leave_ibss, - .add_key = mwifiex_cfg80211_add_key, - .del_key = mwifiex_cfg80211_del_key, - .set_default_key = mwifiex_cfg80211_set_default_key, - .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, - .set_tx_power = mwifiex_cfg80211_set_tx_power, -}; - -/* - * This function registers the device with CFG802.11 subsystem. - * - * The function creates the wireless device/wiphy, populates it with - * default parameters and handler function pointers, and finally - * registers the device. - */ -int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, - struct mwifiex_private *priv) -{ - int ret = 0; - void *wdev_priv = NULL; - struct wireless_dev *wdev; - - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - dev_err(priv->adapter->dev, "%s: allocating wireless device\n", - __func__); - return -ENOMEM; - } - wdev->wiphy = - wiphy_new(&mwifiex_cfg80211_ops, - sizeof(struct mwifiex_private *)); - if (!wdev->wiphy) - return -ENOMEM; - wdev->iftype = NL80211_IFTYPE_STATION; - wdev->wiphy->max_scan_ssids = 10; - wdev->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; - mwifiex_setup_ht_caps( - &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); - - if (priv->adapter->config_bands & BAND_A) { - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; - mwifiex_setup_ht_caps( - &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); - } else { - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - } - - /* Initialize cipher suits */ - wdev->wiphy->cipher_suites = mwifiex_cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); - - memcpy(wdev->wiphy->perm_addr, mac, 6); - wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - /* We are using custom domains */ - wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; - - wdev->wiphy->reg_notifier = mwifiex_reg_notifier; - - /* Set struct mwifiex_private pointer in wiphy_priv */ - wdev_priv = wiphy_priv(wdev->wiphy); - - *(unsigned long *) wdev_priv = (unsigned long) priv; - - ret = wiphy_register(wdev->wiphy); - if (ret < 0) { - dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", - __func__); - wiphy_free(wdev->wiphy); - return ret; - } else { - dev_dbg(priv->adapter->dev, - "info: successfully registered wiphy device\n"); - } - - dev_net_set(dev, wiphy_net(wdev->wiphy)); - dev->ieee80211_ptr = wdev; - memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6); - memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6); - SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); - priv->wdev = wdev; - - dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; - dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; - - return ret; -} - -/* - * This function handles the result of different pending network operations. - * - * The following operations are handled and CFG802.11 subsystem is - * notified accordingly - - * - Scan request completion - * - Association request completion - * - IBSS join request completion - * - Disconnect request completion - */ -void -mwifiex_cfg80211_results(struct work_struct *work) -{ - struct mwifiex_private *priv = - container_of(work, struct mwifiex_private, cfg_workqueue); - struct mwifiex_user_scan_cfg *scan_req; - int ret = 0, i; - struct ieee80211_channel *chan; - - if (priv->scan_request) { - scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg), - GFP_KERNEL); - if (!scan_req) { - dev_err(priv->adapter->dev, "failed to alloc " - "scan_req\n"); - return; - } - for (i = 0; i < priv->scan_request->n_ssids; i++) { - memcpy(scan_req->ssid_list[i].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - scan_req->ssid_list[i].max_len = - priv->scan_request->ssids[i].ssid_len; - } - for (i = 0; i < priv->scan_request->n_channels; i++) { - chan = priv->scan_request->channels[i]; - scan_req->chan_list[i].chan_number = chan->hw_value; - scan_req->chan_list[i].radio_type = chan->band; - if (chan->flags & IEEE80211_CHAN_DISABLED) - scan_req->chan_list[i].scan_type = - MWIFIEX_SCAN_TYPE_PASSIVE; - else - scan_req->chan_list[i].scan_type = - MWIFIEX_SCAN_TYPE_ACTIVE; - scan_req->chan_list[i].scan_time = 0; - } - if (mwifiex_set_user_scan_ioctl(priv, scan_req)) { - ret = -EFAULT; - goto done; - } - if (mwifiex_inform_bss_from_scan_result(priv, NULL)) - ret = -EFAULT; -done: - priv->scan_result_status = ret; - dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", - __func__); - cfg80211_scan_done(priv->scan_request, - (priv->scan_result_status < 0)); - priv->scan_request = NULL; - kfree(scan_req); - } - - if (priv->assoc_request) { - if (!priv->assoc_result) { - cfg80211_connect_result(priv->netdev, priv->cfg_bssid, - NULL, 0, NULL, 0, - WLAN_STATUS_SUCCESS, - GFP_KERNEL); - dev_dbg(priv->adapter->dev, - "info: associated to bssid %pM successfully\n", - priv->cfg_bssid); - } else { - dev_dbg(priv->adapter->dev, - "info: association to bssid %pM failed\n", - priv->cfg_bssid); - memset(priv->cfg_bssid, 0, ETH_ALEN); - } - priv->assoc_request = 0; - priv->assoc_result = 0; - } - - if (priv->ibss_join_request) { - if (!priv->ibss_join_result) { - cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, - GFP_KERNEL); - dev_dbg(priv->adapter->dev, - "info: joined/created adhoc network with bssid" - " %pM successfully\n", priv->cfg_bssid); - } else { - dev_dbg(priv->adapter->dev, - "info: failed creating/joining adhoc network\n"); - } - priv->ibss_join_request = 0; - priv->ibss_join_result = 0; - } - - if (priv->disconnect) { - memset(priv->cfg_bssid, 0, ETH_ALEN); - priv->disconnect = 0; - } -} diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.h b/trunk/drivers/net/wireless/mwifiex/cfg80211.h deleted file mode 100644 index c4db8f36aa16..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Marvell Wireless LAN device driver: CFG80211 - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef __MWIFIEX_CFG80211__ -#define __MWIFIEX_CFG80211__ - -#include - -#include "main.h" - -int mwifiex_register_cfg80211(struct net_device *, u8 *, - struct mwifiex_private *); - -void mwifiex_cfg80211_results(struct work_struct *work); -#endif diff --git a/trunk/drivers/net/wireless/mwifiex/cfp.c b/trunk/drivers/net/wireless/mwifiex/cfp.c deleted file mode 100644 index d0cada5a29a0..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/cfp.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Marvell Wireless LAN device driver: Channel, Frequence and Power - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "cfg80211.h" - -/* 100mW */ -#define MWIFIEX_TX_PWR_DEFAULT 20 -/* 100mW */ -#define MWIFIEX_TX_PWR_US_DEFAULT 20 -/* 50mW */ -#define MWIFIEX_TX_PWR_JP_DEFAULT 16 -/* 100mW */ -#define MWIFIEX_TX_PWR_FR_100MW 20 -/* 10mW */ -#define MWIFIEX_TX_PWR_FR_10MW 10 -/* 100mW */ -#define MWIFIEX_TX_PWR_EMEA_DEFAULT 20 - -static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 }; - -static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, - 0xb0, 0x48, 0x60, 0x6c, 0 }; - -static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, - 0x0c, 0x12, 0x18, 0x24, - 0x30, 0x48, 0x60, 0x6c, 0 }; - -static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, - 0xb0, 0x48, 0x60, 0x6c, 0 }; -u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, - 0xb0, 0x48, 0x60, 0x6c, 0 }; -static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04, - 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, - 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, - 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, - 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, - 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 }; - -u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 }; - -u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, - 0x30, 0x48, 0x60, 0x6c, 0 }; - -u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c, - 0x12, 0x16, 0x18, 0x24, 0x30, 0x48, - 0x60, 0x6c, 0 }; - -u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, - 0x32, 0x40, 0x41, 0xff }; - -u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; - -/* - * This function maps an index in supported rates table into - * the corresponding data rate. - */ -u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info) -{ - u16 mcs_rate[4][8] = { - {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e} - , /* LG 40M */ - {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c} - , /* SG 40M */ - {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82} - , /* LG 20M */ - {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90} - }; /* SG 20M */ - - u32 rate; - - if (ht_info & BIT(0)) { - if (index == MWIFIEX_RATE_BITMAP_MCS0) { - if (ht_info & BIT(2)) - rate = 0x0D; /* MCS 32 SGI rate */ - else - rate = 0x0C; /* MCS 32 LGI rate */ - } else if (index < 8) { - if (ht_info & BIT(1)) { - if (ht_info & BIT(2)) - /* SGI, 40M */ - rate = mcs_rate[1][index]; - else - /* LGI, 40M */ - rate = mcs_rate[0][index]; - } else { - if (ht_info & BIT(2)) - /* SGI, 20M */ - rate = mcs_rate[3][index]; - else - /* LGI, 20M */ - rate = mcs_rate[2][index]; - } - } else - rate = mwifiex_data_rates[0]; - } else { - if (index >= MWIFIEX_SUPPORTED_RATES_EXT) - index = 0; - rate = mwifiex_data_rates[index]; - } - return rate; -} - -/* - * This function maps a data rate value into corresponding index in supported - * rates table. - */ -u8 mwifiex_data_rate_to_index(u32 rate) -{ - u16 *ptr; - - if (rate) { - ptr = memchr(mwifiex_data_rates, rate, - sizeof(mwifiex_data_rates)); - if (ptr) - return (u8) (ptr - mwifiex_data_rates); - } - return 0; -} - -/* - * This function returns the current active data rates. - * - * The result may vary depending upon connection status. - */ -u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates) -{ - if (!priv->media_connected) - return mwifiex_get_supported_rates(priv, rates); - else - return mwifiex_copy_rates(rates, 0, - priv->curr_bss_params.data_rates, - priv->curr_bss_params.num_of_rates); -} - -/* - * This function locates the Channel-Frequency-Power triplet based upon - * band and channel parameters. - */ -struct mwifiex_chan_freq_power * -mwifiex_get_cfp_by_band_and_channel_from_cfg80211(struct mwifiex_private - *priv, u8 band, u16 channel) -{ - struct mwifiex_chan_freq_power *cfp = NULL; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - int i; - - if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) - sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; - else - sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; - - if (!sband) { - dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" - " & channel %d\n", __func__, band, channel); - return cfp; - } - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - if (((ch->hw_value == channel) || - (channel == FIRST_VALID_CHANNEL)) - && !(ch->flags & IEEE80211_CHAN_DISABLED)) { - priv->cfp.channel = channel; - priv->cfp.freq = ch->center_freq; - priv->cfp.max_tx_power = ch->max_power; - cfp = &priv->cfp; - break; - } - } - if (i == sband->n_channels) - dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" - " & channel %d\n", __func__, band, channel); - - return cfp; -} - -/* - * This function locates the Channel-Frequency-Power triplet based upon - * band and frequency parameters. - */ -struct mwifiex_chan_freq_power * -mwifiex_get_cfp_by_band_and_freq_from_cfg80211(struct mwifiex_private *priv, - u8 band, u32 freq) -{ - struct mwifiex_chan_freq_power *cfp = NULL; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - int i; - - if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) - sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; - else - sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; - - if (!sband) { - dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" - " & freq %d\n", __func__, band, freq); - return cfp; - } - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - if ((ch->center_freq == freq) && - !(ch->flags & IEEE80211_CHAN_DISABLED)) { - priv->cfp.channel = ch->hw_value; - priv->cfp.freq = freq; - priv->cfp.max_tx_power = ch->max_power; - cfp = &priv->cfp; - break; - } - } - if (i == sband->n_channels) - dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" - " & freq %d\n", __func__, band, freq); - - return cfp; -} - -/* - * This function checks if the data rate is set to auto. - */ -u8 -mwifiex_is_rate_auto(struct mwifiex_private *priv) -{ - u32 i; - int rate_num = 0; - - for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++) - if (priv->bitmap_rates[i]) - rate_num++; - - if (rate_num > 1) - return true; - else - return false; -} - -/* - * This function converts rate bitmap into rate index. - */ -int mwifiex_get_rate_index(u16 *rate_bitmap, int size) -{ - int i; - - for (i = 0; i < size * 8; i++) - if (rate_bitmap[i / 16] & (1 << (i % 16))) - return i; - - return 0; -} - -/* - * This function gets the supported data rates. - * - * The function works in both Ad-Hoc and infra mode by printing the - * band and returning the data rates. - */ -u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) -{ - u32 k = 0; - struct mwifiex_adapter *adapter = priv->adapter; - if (priv->bss_mode == NL80211_IFTYPE_STATION) { - switch (adapter->config_bands) { - case BAND_B: - dev_dbg(adapter->dev, "info: infra band=%d " - "supported_rates_b\n", adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_b, - sizeof(supported_rates_b)); - break; - case BAND_G: - case BAND_G | BAND_GN: - dev_dbg(adapter->dev, "info: infra band=%d " - "supported_rates_g\n", adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_g, - sizeof(supported_rates_g)); - break; - case BAND_B | BAND_G: - case BAND_A | BAND_B | BAND_G: - case BAND_A | BAND_B: - case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: - case BAND_B | BAND_G | BAND_GN: - dev_dbg(adapter->dev, "info: infra band=%d " - "supported_rates_bg\n", adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_bg, - sizeof(supported_rates_bg)); - break; - case BAND_A: - case BAND_A | BAND_G: - dev_dbg(adapter->dev, "info: infra band=%d " - "supported_rates_a\n", adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_a, - sizeof(supported_rates_a)); - break; - case BAND_A | BAND_AN: - case BAND_A | BAND_G | BAND_AN | BAND_GN: - dev_dbg(adapter->dev, "info: infra band=%d " - "supported_rates_a\n", adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_a, - sizeof(supported_rates_a)); - break; - case BAND_GN: - dev_dbg(adapter->dev, "info: infra band=%d " - "supported_rates_n\n", adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_n, - sizeof(supported_rates_n)); - break; - } - } else { - /* Ad-hoc mode */ - switch (adapter->adhoc_start_band) { - case BAND_B: - dev_dbg(adapter->dev, "info: adhoc B\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_b, - sizeof(adhoc_rates_b)); - break; - case BAND_G: - case BAND_G | BAND_GN: - dev_dbg(adapter->dev, "info: adhoc G only\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_g, - sizeof(adhoc_rates_g)); - break; - case BAND_B | BAND_G: - case BAND_B | BAND_G | BAND_GN: - dev_dbg(adapter->dev, "info: adhoc BG\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_bg, - sizeof(adhoc_rates_bg)); - break; - case BAND_A: - case BAND_A | BAND_AN: - dev_dbg(adapter->dev, "info: adhoc A\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_a, - sizeof(adhoc_rates_a)); - break; - } - } - - return k; -} diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c deleted file mode 100644 index 776146a104ec..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ /dev/null @@ -1,1415 +0,0 @@ -/* - * Marvell Wireless LAN device driver: commands and events - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * This function initializes a command node. - * - * The actual allocation of the node is not done by this function. It only - * initiates a node by filling it with default parameters. Similarly, - * allocation of the different buffers used (IOCTL buffer, data buffer) are - * not done by this function either. - */ -static void -mwifiex_init_cmd_node(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node, - u32 cmd_oid, void *data_buf) -{ - cmd_node->priv = priv; - cmd_node->cmd_oid = cmd_oid; - cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; - priv->adapter->cmd_wait_q_required = false; - cmd_node->data_buf = data_buf; - cmd_node->cmd_skb = cmd_node->skb; -} - -/* - * This function returns a command node from the free queue depending upon - * availability. - */ -static struct cmd_ctrl_node * -mwifiex_get_cmd_node(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_node; - unsigned long flags; - - spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); - if (list_empty(&adapter->cmd_free_q)) { - dev_err(adapter->dev, "GET_CMD_NODE: cmd node not available\n"); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - return NULL; - } - cmd_node = list_first_entry(&adapter->cmd_free_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - - return cmd_node; -} - -/* - * This function cleans up a command node. - * - * The function resets the fields including the buffer pointers. - * This function does not try to free the buffers. They must be - * freed before calling this function. - * - * This function will however call the receive completion callback - * in case a response buffer is still available before resetting - * the pointer. - */ -static void -mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - cmd_node->cmd_oid = 0; - cmd_node->cmd_flag = 0; - cmd_node->data_buf = NULL; - cmd_node->wait_q_enabled = false; - - if (cmd_node->resp_skb) { - mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); - cmd_node->resp_skb = NULL; - } -} - -/* - * This function sends a host command to the firmware. - * - * The function copies the host command into the driver command - * buffer, which will be transferred to the firmware later by the - * main thread. - */ -static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct mwifiex_ds_misc_cmd *pcmd_ptr = - (struct mwifiex_ds_misc_cmd *) data_buf; - - /* Copy the HOST command to command buffer */ - memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len); - dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len); - return 0; -} - -/* - * This function downloads a command to the firmware. - * - * The function performs sanity tests, sets the command sequence - * number and size, converts the header fields to CPU format before - * sending. Afterwards, it logs the command ID and action for debugging - * and sets up the command timeout timer. - */ -static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node) -{ - - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - struct host_cmd_ds_command *host_cmd; - uint16_t cmd_code; - uint16_t cmd_size; - struct timeval tstamp; - unsigned long flags; - - if (!adapter || !cmd_node) - return -1; - - host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - - /* Sanity test */ - if (host_cmd == NULL || host_cmd->size == 0) { - dev_err(adapter->dev, "DNLD_CMD: host_cmd is null" - " or cmd size is 0, not sending\n"); - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - return -1; - } - - /* Set command sequence number */ - adapter->seq_num++; - host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO - (adapter->seq_num, cmd_node->priv->bss_num, - cmd_node->priv->bss_type)); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = cmd_node; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - cmd_code = le16_to_cpu(host_cmd->command); - cmd_size = le16_to_cpu(host_cmd->size); - - skb_trim(cmd_node->cmd_skb, cmd_size); - - do_gettimeofday(&tstamp); - dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," - " seqno %#x\n", - tstamp.tv_sec, tstamp.tv_usec, cmd_code, - le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size, - le16_to_cpu(host_cmd->seq_num)); - - skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN); - - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, - cmd_node->cmd_skb->data, - cmd_node->cmd_skb->len, NULL); - - skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); - - if (ret == -1) { - dev_err(adapter->dev, "DNLD_CMD: host to card failed\n"); - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - adapter->dbg.num_cmd_host_to_card_failure++; - return -1; - } - - /* Save the last command id and action to debug log */ - adapter->dbg.last_cmd_index = - (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; - adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code; - adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] = - le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)); - - /* Clear BSS_NO_BITS from HostCmd */ - cmd_code &= HostCmd_CMD_ID_MASK; - - /* Setup the timer after transmit command */ - mod_timer(&adapter->cmd_timer, - jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000); - - return 0; -} - -/* - * This function downloads a sleep confirm command to the firmware. - * - * The function performs sanity tests, sets the command sequence - * number and size, converts the header fields to CPU format before - * sending. - * - * No responses are needed for sleep confirm command. - */ -static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) -{ - int ret = 0; - u16 cmd_len = 0; - struct mwifiex_private *priv; - struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = - (struct mwifiex_opt_sleep_confirm_buffer *) - adapter->sleep_cfm->data; - cmd_len = sizeof(struct mwifiex_opt_sleep_confirm); - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - sleep_cfm_buf->ps_cfm_sleep.seq_num = - cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO - (adapter->seq_num, priv->bss_num, - priv->bss_type))); - adapter->seq_num++; - - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, - adapter->sleep_cfm->data, - adapter->sleep_cfm->len + - INTF_HEADER_LEN, NULL); - - if (ret == -1) { - dev_err(adapter->dev, "SLEEP_CFM: failed\n"); - adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; - return -1; - } - if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) - == MWIFIEX_BSS_ROLE_STA) { - if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl) - /* Response is not needed for sleep - confirm command */ - adapter->ps_state = PS_STATE_SLEEP; - else - adapter->ps_state = PS_STATE_SLEEP_CFM; - - if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl - && (adapter->is_hs_configured - && !adapter->sleep_period.period)) { - adapter->pm_wakeup_card_req = true; - mwifiex_hs_activated_event(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_STA), true); - } - } - - return ret; -} - -/* - * This function allocates the command buffers and links them to - * the command free queue. - * - * The driver uses a pre allocated number of command buffers, which - * are created at driver initializations and freed at driver cleanup. - * Every command needs to obtain a command buffer from this pool before - * it can be issued. The command free queue lists the command buffers - * currently free to use, while the command pending queue lists the - * command buffers already in use and awaiting handling. Command buffers - * are returned to the free queue after use. - */ -int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_array; - u32 buf_size; - u32 i; - - /* Allocate and initialize struct cmd_ctrl_node */ - buf_size = sizeof(struct cmd_ctrl_node) * MWIFIEX_NUM_OF_CMD_BUFFER; - cmd_array = kzalloc(buf_size, GFP_KERNEL); - if (!cmd_array) { - dev_err(adapter->dev, "%s: failed to alloc cmd_array\n", - __func__); - return -1; - } - - adapter->cmd_pool = cmd_array; - memset(adapter->cmd_pool, 0, buf_size); - - /* Allocate and initialize command buffers */ - for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { - cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); - if (!cmd_array[i].skb) { - dev_err(adapter->dev, "ALLOC_CMD_BUF: out of memory\n"); - return -1; - } - } - - for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) - mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]); - - return 0; -} - -/* - * This function frees the command buffers. - * - * The function calls the completion callback for all the command - * buffers that still have response buffers associated with them. - */ -int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_array; - u32 i; - - /* Need to check if cmd pool is allocated or not */ - if (!adapter->cmd_pool) { - dev_dbg(adapter->dev, "info: FREE_CMD_BUF: cmd_pool is null\n"); - return 0; - } - - cmd_array = adapter->cmd_pool; - - /* Release shared memory buffers */ - for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { - if (cmd_array[i].skb) { - dev_dbg(adapter->dev, "cmd: free cmd buffer %d\n", i); - dev_kfree_skb_any(cmd_array[i].skb); - } - if (!cmd_array[i].resp_skb) - continue; - mwifiex_recv_complete(adapter, cmd_array[i].resp_skb, 0); - } - /* Release struct cmd_ctrl_node */ - if (adapter->cmd_pool) { - dev_dbg(adapter->dev, "cmd: free cmd pool\n"); - kfree(adapter->cmd_pool); - adapter->cmd_pool = NULL; - } - - return 0; -} - -/* - * This function handles events generated by firmware. - * - * Event body of events received from firmware are not used (though they are - * saved), only the event ID is used. Some events are re-invoked by - * the driver, with a new event body. - * - * After processing, the function calls the completion callback - * for cleanup. - */ -int mwifiex_process_event(struct mwifiex_adapter *adapter) -{ - int ret = 0; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - struct sk_buff *skb = adapter->event_skb; - u32 eventcause = adapter->event_cause; - struct timeval tstamp; - struct mwifiex_rxinfo *rx_info = NULL; - - /* Save the last event to debug log */ - adapter->dbg.last_event_index = - (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; - adapter->dbg.last_event[adapter->dbg.last_event_index] = - (u16) eventcause; - - /* Get BSS number and corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), - EVENT_GET_BSS_TYPE(eventcause)); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - /* Clear BSS_NO_BITS from event */ - eventcause &= EVENT_ID_MASK; - adapter->event_cause = eventcause; - - if (skb) { - rx_info = MWIFIEX_SKB_RXCB(skb); - rx_info->bss_index = priv->bss_index; - } - - if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) { - do_gettimeofday(&tstamp); - dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", - tstamp.tv_sec, tstamp.tv_usec, eventcause); - } - - ret = mwifiex_process_sta_event(priv); - - adapter->event_cause = 0; - adapter->event_skb = NULL; - - mwifiex_recv_complete(adapter, skb, 0); - - return ret; -} - -/* - * This function is used to send synchronous command to the firmware. - * - * it allocates a wait queue for the command and wait for the command - * response. - */ -int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, void *data_buf) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - - adapter->cmd_wait_q_required = true; - adapter->cmd_wait_q.condition = false; - - ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, - data_buf); - if (!ret) - ret = mwifiex_wait_queue_complete(adapter); - - return ret; -} - - -/* - * This function prepares a command and asynchronously send it to the firmware. - * - * Preparation includes - - * - Sanity tests to make sure the card is still present or the FW - * is not reset - * - Getting a new command node from the command free queue - * - Initializing the command node for default parameters - * - Fill up the non-default parameters and buffer pointers - * - Add the command to pending queue - */ -int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, void *data_buf) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node = NULL; - struct host_cmd_ds_command *cmd_ptr = NULL; - - if (!adapter) { - pr_err("PREP_CMD: adapter is NULL\n"); - return -1; - } - - if (adapter->is_suspended) { - dev_err(adapter->dev, "PREP_CMD: device in suspended state\n"); - return -1; - } - - if (adapter->surprise_removed) { - dev_err(adapter->dev, "PREP_CMD: card is removed\n"); - return -1; - } - - if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { - if (cmd_no != HostCmd_CMD_FUNC_INIT) { - dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); - return -1; - } - } - - /* Get a new command node */ - cmd_node = mwifiex_get_cmd_node(adapter); - - if (!cmd_node) { - dev_err(adapter->dev, "PREP_CMD: no free cmd node\n"); - return -1; - } - - /* Initialize the command node */ - mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf); - - if (!cmd_node->cmd_skb) { - dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); - return -1; - } - - memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)), - 0, sizeof(struct host_cmd_ds_command)); - - cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->result = 0; - - /* Prepare command */ - if (cmd_no) { - ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, - cmd_oid, data_buf, cmd_ptr); - } else { - ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); - cmd_node->cmd_flag |= CMD_F_HOSTCMD; - } - - /* Return error, since the command preparation failed */ - if (ret) { - dev_err(adapter->dev, "PREP_CMD: cmd %#x preparation failed\n", - cmd_no); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - return -1; - } - - /* Send command */ - if (cmd_no == HostCmd_CMD_802_11_SCAN) - mwifiex_queue_scan_cmd(priv, cmd_node); - else - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); - - return ret; -} - -/* - * This function returns a command to the command free queue. - * - * The function also calls the completion callback if required, before - * cleaning the command node and re-inserting it into the free queue. - */ -void -mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - unsigned long flags; - - if (!cmd_node) - return; - - if (cmd_node->wait_q_enabled) - mwifiex_complete_cmd(adapter); - /* Clean the node */ - mwifiex_clean_cmd_node(adapter, cmd_node); - - /* Insert node into cmd_free_q */ - spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); - list_add_tail(&cmd_node->list, &adapter->cmd_free_q); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); -} - -/* - * This function queues a command to the command pending queue. - * - * This in effect adds the command to the command list to be executed. - * Exit PS command is handled specially, by placing it always to the - * front of the command queue. - */ -void -mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node, u32 add_tail) -{ - struct host_cmd_ds_command *host_cmd = NULL; - u16 command; - unsigned long flags; - - host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - if (!host_cmd) { - dev_err(adapter->dev, "QUEUE_CMD: host_cmd is NULL\n"); - return; - } - - command = le16_to_cpu(host_cmd->command); - - /* Exit_PS command needs to be queued in the header always. */ - if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { - struct host_cmd_ds_802_11_ps_mode_enh *pm = - &host_cmd->params.psmode_enh; - if ((le16_to_cpu(pm->action) == DIS_PS) - || (le16_to_cpu(pm->action) == DIS_AUTO_PS)) { - if (adapter->ps_state != PS_STATE_AWAKE) - add_tail = false; - } - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - if (add_tail) - list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); - else - list_add(&cmd_node->list, &adapter->cmd_pending_q); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); -} - -/* - * This function executes the next command in command pending queue. - * - * This function will fail if a command is already in processing stage, - * otherwise it will dequeue the first command from the command pending - * queue and send to the firmware. - * - * If the device is currently in host sleep mode, any commands, except the - * host sleep configuration command will de-activate the host sleep. For PS - * mode, the function will put the firmware back to sleep if applicable. - */ -int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv = NULL; - struct cmd_ctrl_node *cmd_node = NULL; - int ret = 0; - struct host_cmd_ds_command *host_cmd; - unsigned long cmd_flags; - unsigned long cmd_pending_q_flags; - - /* Check if already in processing */ - if (adapter->curr_cmd) { - dev_err(adapter->dev, "EXEC_NEXT_CMD: cmd in processing\n"); - return -1; - } - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - /* Check if any command is pending */ - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); - if (list_empty(&adapter->cmd_pending_q)) { - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - return 0; - } - cmd_node = list_first_entry(&adapter->cmd_pending_q, - struct cmd_ctrl_node, list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - - host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - priv = cmd_node->priv; - - if (adapter->ps_state != PS_STATE_AWAKE) { - dev_err(adapter->dev, "%s: cannot send cmd in sleep state," - " this should not happen\n", __func__); - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - return ret; - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node); - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - /* Any command sent to the firmware when host is in sleep - * mode should de-configure host sleep. We should skip the - * host sleep configuration command itself though - */ - if (priv && (host_cmd->command != - cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) { - if (adapter->hs_activated) { - adapter->is_hs_configured = false; - mwifiex_hs_activated_event(priv, false); - } - } - - return ret; -} - -/* - * This function handles the command response. - * - * After processing, the function cleans the command node and puts - * it back to the command free queue. - */ -int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) -{ - struct host_cmd_ds_command *resp = NULL; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - int ret = 0; - uint16_t orig_cmdresp_no; - uint16_t cmdresp_no; - uint16_t cmdresp_result; - struct timeval tstamp; - unsigned long flags; - - /* Now we got response from FW, cancel the command timer */ - del_timer(&adapter->cmd_timer); - - if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { - resp = (struct host_cmd_ds_command *) adapter->upld_buf; - dev_err(adapter->dev, "CMD_RESP: NULL curr_cmd, %#x\n", - le16_to_cpu(resp->command)); - return -1; - } - - adapter->num_cmd_timeout = 0; - - resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; - if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { - dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", - le16_to_cpu(resp->command)); - mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - return -1; - } - - if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { - /* Copy original response back to response buffer */ - struct mwifiex_ds_misc_cmd *hostcmd = NULL; - uint16_t size = le16_to_cpu(resp->size); - dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size); - size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER); - if (adapter->curr_cmd->data_buf) { - hostcmd = (struct mwifiex_ds_misc_cmd *) - adapter->curr_cmd->data_buf; - hostcmd->len = size; - memcpy(hostcmd->cmd, (void *) resp, size); - } - } - orig_cmdresp_no = le16_to_cpu(resp->command); - - /* Get BSS number and corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, - HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)), - HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - /* Clear RET_BIT from HostCmd */ - resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK); - - cmdresp_no = le16_to_cpu(resp->command); - cmdresp_result = le16_to_cpu(resp->result); - - /* Save the last command response to debug log */ - adapter->dbg.last_cmd_resp_index = - (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; - adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = - orig_cmdresp_no; - - do_gettimeofday(&tstamp); - dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d," - " len %d, seqno 0x%x\n", - tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result, - le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); - - if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { - dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); - if (adapter->curr_cmd->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - - mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - return -1; - } - - if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { - adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD; - if ((cmdresp_result == HostCmd_RESULT_OK) - && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH)) - ret = mwifiex_ret_802_11_hs_cfg(priv, resp); - } else { - /* handle response */ - ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp); - } - - /* Check init command response */ - if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { - if (ret == -1) { - dev_err(adapter->dev, "%s: cmd %#x failed during " - "initialization\n", __func__, cmdresp_no); - mwifiex_init_fw_complete(adapter); - return -1; - } else if (adapter->last_init_cmd == cmdresp_no) - adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE; - } - - if (adapter->curr_cmd) { - if (adapter->curr_cmd->wait_q_enabled && (!ret)) - adapter->cmd_wait_q.status = 0; - else if (adapter->curr_cmd->wait_q_enabled && (ret == -1)) - adapter->cmd_wait_q.status = -1; - - /* Clean up and put current command back to cmd_free_q */ - mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - } - - return ret; -} - -/* - * This function handles the timeout of command sending. - * - * It will re-send the same command again. - */ -void -mwifiex_cmd_timeout_func(unsigned long function_context) -{ - struct mwifiex_adapter *adapter = - (struct mwifiex_adapter *) function_context; - struct cmd_ctrl_node *cmd_node = NULL; - struct timeval tstamp; - - adapter->num_cmd_timeout++; - adapter->dbg.num_cmd_timeout++; - if (!adapter->curr_cmd) { - dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); - return; - } - cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - - if (cmd_node) { - adapter->dbg.timeout_cmd_id = - adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; - adapter->dbg.timeout_cmd_act = - adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; - do_gettimeofday(&tstamp); - dev_err(adapter->dev, "%s: Timeout cmd id (%lu.%lu) = %#x," - " act = %#x\n", __func__, - tstamp.tv_sec, tstamp.tv_usec, - adapter->dbg.timeout_cmd_id, - adapter->dbg.timeout_cmd_act); - - dev_err(adapter->dev, "num_data_h2c_failure = %d\n", - adapter->dbg.num_tx_host_to_card_failure); - dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", - adapter->dbg.num_cmd_host_to_card_failure); - - dev_err(adapter->dev, "num_cmd_timeout = %d\n", - adapter->dbg.num_cmd_timeout); - dev_err(adapter->dev, "num_tx_timeout = %d\n", - adapter->dbg.num_tx_timeout); - - dev_err(adapter->dev, "last_cmd_index = %d\n", - adapter->dbg.last_cmd_index); - print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET, - adapter->dbg.last_cmd_id, DBG_CMD_NUM); - print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET, - adapter->dbg.last_cmd_act, DBG_CMD_NUM); - - dev_err(adapter->dev, "last_cmd_resp_index = %d\n", - adapter->dbg.last_cmd_resp_index); - print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET, - adapter->dbg.last_cmd_resp_id, DBG_CMD_NUM); - - dev_err(adapter->dev, "last_event_index = %d\n", - adapter->dbg.last_event_index); - print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET, - adapter->dbg.last_event, DBG_CMD_NUM); - - dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n", - adapter->data_sent, adapter->cmd_sent); - - dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", - adapter->ps_mode, adapter->ps_state); - } - if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) - mwifiex_init_fw_complete(adapter); -} - -/* - * This function cancels all the pending commands. - * - * The current command, all commands in command pending queue and all scan - * commands in scan pending queue are cancelled. All the completion callbacks - * are called with failure status to ensure cleanup. - */ -void -mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - unsigned long flags; - - /* Cancel current cmd */ - if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd->wait_q_enabled = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - adapter->cmd_wait_q.status = -1; - mwifiex_complete_cmd(adapter); - } - /* Cancel all pending command */ - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->cmd_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - if (cmd_node->wait_q_enabled) { - adapter->cmd_wait_q.status = -1; - mwifiex_complete_cmd(adapter); - cmd_node->wait_q_enabled = false; - } - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -} - -/* - * This function cancels all pending commands that matches with - * the given IOCTL request. - * - * Both the current command buffer and the pending command queue are - * searched for matching IOCTL request. The completion callback of - * the matched command is called with failure status to ensure cleanup. - * In case of scan commands, all pending commands in scan pending queue - * are cancelled. - */ -void -mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - unsigned long cmd_flags; - unsigned long cmd_pending_q_flags; - unsigned long scan_pending_q_flags; - uint16_t cancel_scan_cmd = false; - - if ((adapter->curr_cmd) && - (adapter->curr_cmd->wait_q_enabled)) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - cmd_node = adapter->curr_cmd; - cmd_node->wait_q_enabled = false; - cmd_node->cmd_flag |= CMD_F_CANCELED; - spin_lock_irqsave(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - } - - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - cancel_scan_cmd = true; - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - - if (cancel_scan_cmd) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - } - adapter->cmd_wait_q.status = -1; - mwifiex_complete_cmd(adapter); -} - -/* - * This function sends the sleep confirm command to firmware, if - * possible. - * - * The sleep confirm command cannot be issued if command response, - * data response or event response is awaiting handling, or if we - * are in the middle of sending a command, or expecting a command - * response. - */ -void -mwifiex_check_ps_cond(struct mwifiex_adapter *adapter) -{ - if (!adapter->cmd_sent && - !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) - mwifiex_dnld_sleep_confirm_cmd(adapter); - else - dev_dbg(adapter->dev, - "cmd: Delay Sleep Confirm (%s%s%s)\n", - (adapter->cmd_sent) ? "D" : "", - (adapter->curr_cmd) ? "C" : "", - (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); -} - -/* - * This function sends a Host Sleep activated event to applications. - * - * This event is generated by the driver, with a blank event body. - */ -void -mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) -{ - if (activated) { - if (priv->adapter->is_hs_configured) { - priv->adapter->hs_activated = true; - dev_dbg(priv->adapter->dev, "event: hs_activated\n"); - priv->adapter->hs_activate_wait_q_woken = true; - wake_up_interruptible( - &priv->adapter->hs_activate_wait_q); - } else { - dev_dbg(priv->adapter->dev, "event: HS not configured\n"); - } - } else { - dev_dbg(priv->adapter->dev, "event: hs_deactivated\n"); - priv->adapter->hs_activated = false; - } -} - -/* - * This function handles the command response of a Host Sleep configuration - * command. - * - * Handling includes changing the header fields into CPU format - * and setting the current host sleep activation status in driver. - * - * In case host sleep status change, the function generates an event to - * notify the applications. - */ -int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg = - &resp->params.opt_hs_cfg; - uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); - - if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) { - mwifiex_hs_activated_event(priv, true); - return 0; - } else { - dev_dbg(adapter->dev, "cmd: CMD_RESP: HS_CFG cmd reply" - " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n", - resp->result, conditions, - phs_cfg->params.hs_config.gpio, - phs_cfg->params.hs_config.gap); - } - if (conditions != HOST_SLEEP_CFG_CANCEL) { - adapter->is_hs_configured = true; - } else { - adapter->is_hs_configured = false; - if (adapter->hs_activated) - mwifiex_hs_activated_event(priv, false); - } - - return 0; -} - -/* - * This function wakes up the adapter and generates a Host Sleep - * cancel event on receiving the power up interrupt. - */ -void -mwifiex_process_hs_config(struct mwifiex_adapter *adapter) -{ - dev_dbg(adapter->dev, "info: %s: auto cancelling host sleep" - " since there is interrupt from the firmware\n", __func__); - - adapter->if_ops.wakeup(adapter); - adapter->hs_activated = false; - adapter->is_hs_configured = false; - mwifiex_hs_activated_event(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY), false); -} - -/* - * This function handles the command response of a sleep confirm command. - * - * The function sets the card state to SLEEP if the response indicates success. - */ -void -mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter, - u8 *pbuf, u32 upld_len) -{ - struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - uint16_t result = le16_to_cpu(cmd->result); - uint16_t command = le16_to_cpu(cmd->command); - uint16_t seq_num = le16_to_cpu(cmd->seq_num); - - if (!upld_len) { - dev_err(adapter->dev, "%s: cmd size is 0\n", __func__); - return; - } - - /* Get BSS number and corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), - HostCmd_GET_BSS_TYPE(seq_num)); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - /* Update sequence number */ - seq_num = HostCmd_GET_SEQ_NO(seq_num); - /* Clear RET_BIT from HostCmd */ - command &= HostCmd_CMD_ID_MASK; - - if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { - dev_err(adapter->dev, "%s: received unexpected response for" - " cmd %x, result = %x\n", __func__, command, result); - return; - } - - if (result) { - dev_err(adapter->dev, "%s: sleep confirm cmd failed\n", - __func__); - adapter->pm_wakeup_card_req = false; - adapter->ps_state = PS_STATE_AWAKE; - return; - } - adapter->pm_wakeup_card_req = true; - if (adapter->is_hs_configured) - mwifiex_hs_activated_event(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY), true); - adapter->ps_state = PS_STATE_SLEEP; - cmd->command = cpu_to_le16(command); - cmd->seq_num = cpu_to_le16(seq_num); -} -EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp); - -/* - * This function prepares an enhanced power mode command. - * - * This function can be used to disable power save or to configure - * power save with auto PS or STA PS or auto deep sleep. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting Power Save bitmap, PS parameters TLV, PS mode TLV, - * auto deep sleep TLV (as required) - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, uint16_t ps_bitmap, - void *data_buf) -{ - struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = - &cmd->params.psmode_enh; - u8 *tlv = NULL; - u16 cmd_size = 0; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); - if (cmd_action == DIS_AUTO_PS) { - psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); - psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + - sizeof(psmode_enh->params.ps_bitmap)); - } else if (cmd_action == GET_PS) { - psmode_enh->action = cpu_to_le16(GET_PS); - psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + - sizeof(psmode_enh->params.ps_bitmap)); - } else if (cmd_action == EN_AUTO_PS) { - psmode_enh->action = cpu_to_le16(EN_AUTO_PS); - psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd_size = S_DS_GEN + sizeof(psmode_enh->action) + - sizeof(psmode_enh->params.ps_bitmap); - tlv = (u8 *) cmd + cmd_size; - if (ps_bitmap & BITMAP_STA_PS) { - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_ps_param *ps_tlv = - (struct mwifiex_ie_types_ps_param *) tlv; - struct mwifiex_ps_param *ps_mode = &ps_tlv->param; - ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM); - ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) - - sizeof(struct mwifiex_ie_types_header)); - cmd_size += sizeof(*ps_tlv); - tlv += sizeof(*ps_tlv); - dev_dbg(adapter->dev, "cmd: PS Command: Enter PS\n"); - ps_mode->null_pkt_interval = - cpu_to_le16(adapter->null_pkt_interval); - ps_mode->multiple_dtims = - cpu_to_le16(adapter->multiple_dtim); - ps_mode->bcn_miss_timeout = - cpu_to_le16(adapter->bcn_miss_time_out); - ps_mode->local_listen_interval = - cpu_to_le16(adapter->local_listen_interval); - ps_mode->adhoc_wake_period = - cpu_to_le16(adapter->adhoc_awake_period); - ps_mode->delay_to_ps = - cpu_to_le16(adapter->delay_to_ps); - ps_mode->mode = - cpu_to_le16(adapter->enhanced_ps_mode); - - } - if (ps_bitmap & BITMAP_AUTO_DS) { - struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv = - (struct mwifiex_ie_types_auto_ds_param *) tlv; - u16 idletime = 0; - - auto_ds_tlv->header.type = - cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); - auto_ds_tlv->header.len = - cpu_to_le16(sizeof(*auto_ds_tlv) - - sizeof(struct mwifiex_ie_types_header)); - cmd_size += sizeof(*auto_ds_tlv); - tlv += sizeof(*auto_ds_tlv); - if (data_buf) - idletime = ((struct mwifiex_ds_auto_ds *) - data_buf)->idle_time; - dev_dbg(priv->adapter->dev, - "cmd: PS Command: Enter Auto Deep Sleep\n"); - auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); - } - cmd->size = cpu_to_le16(cmd_size); - } - return 0; -} - -/* - * This function handles the command response of an enhanced power mode - * command. - * - * Handling includes changing the header fields into CPU format - * and setting the current enhanced power mode in driver. - */ -int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = - &resp->params.psmode_enh; - uint16_t action = le16_to_cpu(ps_mode->action); - uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); - uint16_t auto_ps_bitmap = - le16_to_cpu(ps_mode->params.ps_bitmap); - - dev_dbg(adapter->dev, "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", - __func__, resp->result, action); - if (action == EN_AUTO_PS) { - if (auto_ps_bitmap & BITMAP_AUTO_DS) { - dev_dbg(adapter->dev, "cmd: Enabled auto deep sleep\n"); - priv->adapter->is_deep_sleep = true; - } - if (auto_ps_bitmap & BITMAP_STA_PS) { - dev_dbg(adapter->dev, "cmd: Enabled STA power save\n"); - if (adapter->sleep_period.period) - dev_dbg(adapter->dev, "cmd: set to uapsd/pps mode\n"); - } - } else if (action == DIS_AUTO_PS) { - if (ps_bitmap & BITMAP_AUTO_DS) { - priv->adapter->is_deep_sleep = false; - dev_dbg(adapter->dev, "cmd: Disabled auto deep sleep\n"); - } - if (ps_bitmap & BITMAP_STA_PS) { - dev_dbg(adapter->dev, "cmd: Disabled STA power save\n"); - if (adapter->sleep_period.period) { - adapter->delay_null_pkt = false; - adapter->tx_lock_flag = false; - adapter->pps_uapsd_mode = false; - } - } - } else if (action == GET_PS) { - if (ps_bitmap & BITMAP_STA_PS) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - else - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - - dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap); - - if (data_buf) { - /* This section is for get power save mode */ - struct mwifiex_ds_pm_cfg *pm_cfg = - (struct mwifiex_ds_pm_cfg *)data_buf; - if (ps_bitmap & BITMAP_STA_PS) - pm_cfg->param.ps_mode = 1; - else - pm_cfg->param.ps_mode = 0; - } - } - return 0; -} - -/* - * This function prepares command to get hardware specifications. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting permanent address parameter - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd) -{ - struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec; - - cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN); - memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); - - return 0; -} - -/* - * This function handles the command response of get hardware - * specifications. - * - * Handling includes changing the header fields into CPU format - * and saving/updating the following parameters in driver - - * - Firmware capability information - * - Firmware band settings - * - Ad-hoc start band and channel - * - Ad-hoc 11n activation status - * - Firmware release number - * - Number of antennas - * - Hardware address - * - Hardware interface version - * - Firmware version - * - Region code - * - 11n capabilities - * - MCS support fields - * - MP end port - */ -int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; - struct mwifiex_adapter *adapter = priv->adapter; - int i; - - adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); - - if (IS_SUPPORT_MULTI_BANDS(adapter)) - adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter); - else - adapter->fw_bands = BAND_B; - - adapter->config_bands = adapter->fw_bands; - - if (adapter->fw_bands & BAND_A) { - if (adapter->fw_bands & BAND_GN) { - adapter->config_bands |= BAND_AN; - adapter->fw_bands |= BAND_AN; - } - if (adapter->fw_bands & BAND_AN) { - adapter->adhoc_start_band = BAND_A | BAND_AN; - adapter->adhoc_11n_enabled = true; - } else { - adapter->adhoc_start_band = BAND_A; - } - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A; - } else if (adapter->fw_bands & BAND_GN) { - adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - adapter->adhoc_11n_enabled = true; - } else if (adapter->fw_bands & BAND_G) { - adapter->adhoc_start_band = BAND_G | BAND_B; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - } else if (adapter->fw_bands & BAND_B) { - adapter->adhoc_start_band = BAND_B; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - } - - adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); - adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); - - dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", - adapter->fw_release_number); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", - hw_spec->permanent_addr); - dev_dbg(adapter->dev, "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n", - le16_to_cpu(hw_spec->hw_if_version), - le16_to_cpu(hw_spec->version)); - - if (priv->curr_addr[0] == 0xff) - memmove(priv->curr_addr, hw_spec->permanent_addr, ETH_ALEN); - - adapter->region_code = le16_to_cpu(hw_spec->region_code); - - for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) - /* Use the region code to search for the index */ - if (adapter->region_code == region_code_index[i]) - break; - - /* If it's unidentified region code, use the default (USA) */ - if (i >= MWIFIEX_MAX_REGION_CODE) { - adapter->region_code = 0x10; - dev_dbg(adapter->dev, "cmd: unknown region code, use default (USA)\n"); - } - - adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); - adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; - - if (adapter->if_ops.update_mp_end_port) - adapter->if_ops.update_mp_end_port(adapter, - le16_to_cpu(hw_spec->mp_end_port)); - - return 0; -} diff --git a/trunk/drivers/net/wireless/mwifiex/debugfs.c b/trunk/drivers/net/wireless/mwifiex/debugfs.c deleted file mode 100644 index 7ddcb062f103..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/debugfs.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Marvell Wireless LAN device driver: debugfs - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include - -#include "main.h" -#include "11n.h" - - -static struct dentry *mwifiex_dfs_dir; - -static char *bss_modes[] = { - "Unknown", - "Managed", - "Ad-hoc", - "Auto" -}; - -/* size/addr for mwifiex_debug_info */ -#define item_size(n) (FIELD_SIZEOF(struct mwifiex_debug_info, n)) -#define item_addr(n) (offsetof(struct mwifiex_debug_info, n)) - -/* size/addr for struct mwifiex_adapter */ -#define adapter_item_size(n) (FIELD_SIZEOF(struct mwifiex_adapter, n)) -#define adapter_item_addr(n) (offsetof(struct mwifiex_adapter, n)) - -struct mwifiex_debug_data { - char name[32]; /* variable/array name */ - u32 size; /* size of the variable/array */ - size_t addr; /* address of the variable/array */ - int num; /* number of variables in an array */ -}; - -static struct mwifiex_debug_data items[] = { - {"int_counter", item_size(int_counter), - item_addr(int_counter), 1}, - {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]), - item_addr(packets_out[WMM_AC_VO]), 1}, - {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]), - item_addr(packets_out[WMM_AC_VI]), 1}, - {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]), - item_addr(packets_out[WMM_AC_BE]), 1}, - {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]), - item_addr(packets_out[WMM_AC_BK]), 1}, - {"max_tx_buf_size", item_size(max_tx_buf_size), - item_addr(max_tx_buf_size), 1}, - {"tx_buf_size", item_size(tx_buf_size), - item_addr(tx_buf_size), 1}, - {"curr_tx_buf_size", item_size(curr_tx_buf_size), - item_addr(curr_tx_buf_size), 1}, - {"ps_mode", item_size(ps_mode), - item_addr(ps_mode), 1}, - {"ps_state", item_size(ps_state), - item_addr(ps_state), 1}, - {"is_deep_sleep", item_size(is_deep_sleep), - item_addr(is_deep_sleep), 1}, - {"wakeup_dev_req", item_size(pm_wakeup_card_req), - item_addr(pm_wakeup_card_req), 1}, - {"wakeup_tries", item_size(pm_wakeup_fw_try), - item_addr(pm_wakeup_fw_try), 1}, - {"hs_configured", item_size(is_hs_configured), - item_addr(is_hs_configured), 1}, - {"hs_activated", item_size(hs_activated), - item_addr(hs_activated), 1}, - {"num_tx_timeout", item_size(num_tx_timeout), - item_addr(num_tx_timeout), 1}, - {"num_cmd_timeout", item_size(num_cmd_timeout), - item_addr(num_cmd_timeout), 1}, - {"timeout_cmd_id", item_size(timeout_cmd_id), - item_addr(timeout_cmd_id), 1}, - {"timeout_cmd_act", item_size(timeout_cmd_act), - item_addr(timeout_cmd_act), 1}, - {"last_cmd_id", item_size(last_cmd_id), - item_addr(last_cmd_id), DBG_CMD_NUM}, - {"last_cmd_act", item_size(last_cmd_act), - item_addr(last_cmd_act), DBG_CMD_NUM}, - {"last_cmd_index", item_size(last_cmd_index), - item_addr(last_cmd_index), 1}, - {"last_cmd_resp_id", item_size(last_cmd_resp_id), - item_addr(last_cmd_resp_id), DBG_CMD_NUM}, - {"last_cmd_resp_index", item_size(last_cmd_resp_index), - item_addr(last_cmd_resp_index), 1}, - {"last_event", item_size(last_event), - item_addr(last_event), DBG_CMD_NUM}, - {"last_event_index", item_size(last_event_index), - item_addr(last_event_index), 1}, - {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), - item_addr(num_cmd_host_to_card_failure), 1}, - {"num_cmd_sleep_cfm_fail", - item_size(num_cmd_sleep_cfm_host_to_card_failure), - item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1}, - {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure), - item_addr(num_tx_host_to_card_failure), 1}, - {"num_evt_deauth", item_size(num_event_deauth), - item_addr(num_event_deauth), 1}, - {"num_evt_disassoc", item_size(num_event_disassoc), - item_addr(num_event_disassoc), 1}, - {"num_evt_link_lost", item_size(num_event_link_lost), - item_addr(num_event_link_lost), 1}, - {"num_cmd_deauth", item_size(num_cmd_deauth), - item_addr(num_cmd_deauth), 1}, - {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success), - item_addr(num_cmd_assoc_success), 1}, - {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure), - item_addr(num_cmd_assoc_failure), 1}, - {"cmd_sent", item_size(cmd_sent), - item_addr(cmd_sent), 1}, - {"data_sent", item_size(data_sent), - item_addr(data_sent), 1}, - {"cmd_resp_received", item_size(cmd_resp_received), - item_addr(cmd_resp_received), 1}, - {"event_received", item_size(event_received), - item_addr(event_received), 1}, - - /* variables defined in struct mwifiex_adapter */ - {"cmd_pending", adapter_item_size(cmd_pending), - adapter_item_addr(cmd_pending), 1}, - {"tx_pending", adapter_item_size(tx_pending), - adapter_item_addr(tx_pending), 1}, - {"rx_pending", adapter_item_size(rx_pending), - adapter_item_addr(rx_pending), 1}, -}; - -static int num_of_items = ARRAY_SIZE(items); - -/* - * Generic proc file open handler. - * - * This function is called every time a file is accessed for read or write. - */ -static int -mwifiex_open_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -/* - * Proc info file read handler. - * - * This function is called when the 'info' file is opened for reading. - * It prints the following driver related information - - * - Driver name - * - Driver version - * - Driver extended version - * - Interface name - * - BSS mode - * - Media state (connected or disconnected) - * - MAC address - * - Total number of Tx bytes - * - Total number of Rx bytes - * - Total number of Tx packets - * - Total number of Rx packets - * - Total number of dropped Tx packets - * - Total number of dropped Rx packets - * - Total number of corrupted Tx packets - * - Total number of corrupted Rx packets - * - Carrier status (on or off) - * - Tx queue status (started or stopped) - * - * For STA mode drivers, it also prints the following extra - - * - ESSID - * - BSSID - * - Channel - * - Region code - * - Multicast count - * - Multicast addresses - */ -static ssize_t -mwifiex_info_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - struct net_device *netdev = priv->netdev; - struct netdev_hw_addr *ha; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *) page, fmt[64]; - struct mwifiex_bss_info info; - ssize_t ret = 0; - int i = 0; - - if (!p) - return -ENOMEM; - - memset(&info, 0, sizeof(info)); - ret = mwifiex_get_bss_info(priv, &info); - if (ret) - goto free_and_exit; - - mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); - - if (!priv->version_str[0]) - mwifiex_get_ver_ext(priv); - - p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); - p += sprintf(p, "driver_version = %s", fmt); - p += sprintf(p, "\nverext = %s", priv->version_str); - p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); - p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); - p += sprintf(p, "media_state=\"%s\"\n", - (!priv->media_connected ? "Disconnected" : "Connected")); - p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", - netdev->dev_addr[0], netdev->dev_addr[1], - netdev->dev_addr[2], netdev->dev_addr[3], - netdev->dev_addr[4], netdev->dev_addr[5]); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { - p += sprintf(p, "multicast_count=\"%d\"\n", - netdev_mc_count(netdev)); - p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); - p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", - info.bssid[0], info.bssid[1], - info.bssid[2], info.bssid[3], - info.bssid[4], info.bssid[5]); - p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); - p += sprintf(p, "region_code = \"%02x\"\n", info.region_code); - - netdev_for_each_mc_addr(ha, netdev) - p += sprintf(p, "multicast_address[%d]=" - "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++, - ha->addr[0], ha->addr[1], - ha->addr[2], ha->addr[3], - ha->addr[4], ha->addr[5]); - } - - p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); - p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); - p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); - p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); - p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); - p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); - p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); - p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); - p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) - ? "on" : "off")); - p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev)) - ? "stopped" : "started")); - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, - (unsigned long) p - page); - -free_and_exit: - free_page(page); - return ret; -} - -/* - * Proc getlog file read handler. - * - * This function is called when the 'getlog' file is opened for reading - * It prints the following log information - - * - Number of multicast Tx frames - * - Number of failed packets - * - Number of Tx retries - * - Number of multicast Tx retries - * - Number of duplicate frames - * - Number of RTS successes - * - Number of RTS failures - * - Number of ACK failures - * - Number of fragmented Rx frames - * - Number of multicast Rx frames - * - Number of FCS errors - * - Number of Tx frames - * - WEP ICV error counts - */ -static ssize_t -mwifiex_getlog_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *) page; - ssize_t ret = 0; - struct mwifiex_ds_get_stats stats; - - if (!p) - return -ENOMEM; - - memset(&stats, 0, sizeof(stats)); - ret = mwifiex_get_stats_info(priv, &stats); - if (ret) - goto free_and_exit; - - p += sprintf(p, "\n" - "mcasttxframe %u\n" - "failed %u\n" - "retry %u\n" - "multiretry %u\n" - "framedup %u\n" - "rtssuccess %u\n" - "rtsfailure %u\n" - "ackfailure %u\n" - "rxfrag %u\n" - "mcastrxframe %u\n" - "fcserror %u\n" - "txframe %u\n" - "wepicverrcnt-1 %u\n" - "wepicverrcnt-2 %u\n" - "wepicverrcnt-3 %u\n" - "wepicverrcnt-4 %u\n", - stats.mcast_tx_frame, - stats.failed, - stats.retry, - stats.multi_retry, - stats.frame_dup, - stats.rts_success, - stats.rts_failure, - stats.ack_failure, - stats.rx_frag, - stats.mcast_rx_frame, - stats.fcs_error, - stats.tx_frame, - stats.wep_icv_error[0], - stats.wep_icv_error[1], - stats.wep_icv_error[2], - stats.wep_icv_error[3]); - - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, - (unsigned long) p - page); - -free_and_exit: - free_page(page); - return ret; -} - -static struct mwifiex_debug_info info; - -/* - * Proc debug file read handler. - * - * This function is called when the 'debug' file is opened for reading - * It prints the following log information - - * - Interrupt count - * - WMM AC VO packets count - * - WMM AC VI packets count - * - WMM AC BE packets count - * - WMM AC BK packets count - * - Maximum Tx buffer size - * - Tx buffer size - * - Current Tx buffer size - * - Power Save mode - * - Power Save state - * - Deep Sleep status - * - Device wakeup required status - * - Number of wakeup tries - * - Host Sleep configured status - * - Host Sleep activated status - * - Number of Tx timeouts - * - Number of command timeouts - * - Last timed out command ID - * - Last timed out command action - * - Last command ID - * - Last command action - * - Last command index - * - Last command response ID - * - Last command response index - * - Last event - * - Last event index - * - Number of host to card command failures - * - Number of sleep confirm command failures - * - Number of host to card data failure - * - Number of deauthentication events - * - Number of disassociation events - * - Number of link lost events - * - Number of deauthentication commands - * - Number of association success commands - * - Number of association failure commands - * - Number of commands sent - * - Number of data packets sent - * - Number of command responses received - * - Number of events received - * - Tx BA stream table (TID, RA) - * - Rx reorder table (TID, TA, Start window, Window size, Buffer) - */ -static ssize_t -mwifiex_debug_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - struct mwifiex_debug_data *d = &items[0]; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *) page; - ssize_t ret = 0; - size_t size, addr; - long val; - int i, j; - - if (!p) - return -ENOMEM; - - ret = mwifiex_get_debug_info(priv, &info); - if (ret) - goto free_and_exit; - - for (i = 0; i < num_of_items; i++) { - p += sprintf(p, "%s=", d[i].name); - - size = d[i].size / d[i].num; - - if (i < (num_of_items - 3)) - addr = d[i].addr + (size_t) &info; - else /* The last 3 items are struct mwifiex_adapter variables */ - addr = d[i].addr + (size_t) priv->adapter; - - for (j = 0; j < d[i].num; j++) { - switch (size) { - case 1: - val = *((u8 *) addr); - break; - case 2: - val = *((u16 *) addr); - break; - case 4: - val = *((u32 *) addr); - break; - case 8: - val = *((long long *) addr); - break; - default: - val = -1; - break; - } - - p += sprintf(p, "%#lx ", val); - addr += size; - } - - p += sprintf(p, "\n"); - } - - if (info.tx_tbl_num) { - p += sprintf(p, "Tx BA stream table:\n"); - for (i = 0; i < info.tx_tbl_num; i++) - p += sprintf(p, "tid = %d, " - "ra = %02x:%02x:%02x:%02x:%02x:%02x\n", - info.tx_tbl[i].tid, info.tx_tbl[i].ra[0], - info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2], - info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4], - info.tx_tbl[i].ra[5]); - } - - if (info.rx_tbl_num) { - p += sprintf(p, "Rx reorder table:\n"); - for (i = 0; i < info.rx_tbl_num; i++) { - - p += sprintf(p, "tid = %d, " - "ta = %02x:%02x:%02x:%02x:%02x:%02x, " - "start_win = %d, " - "win_size = %d, buffer: ", - info.rx_tbl[i].tid, - info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1], - info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3], - info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5], - info.rx_tbl[i].start_win, - info.rx_tbl[i].win_size); - - for (j = 0; j < info.rx_tbl[i].win_size; j++) - p += sprintf(p, "%c ", - info.rx_tbl[i].buffer[j] ? - '1' : '0'); - - p += sprintf(p, "\n"); - } - } - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, - (unsigned long) p - page); - -free_and_exit: - free_page(page); - return ret; -} - -static u32 saved_reg_type, saved_reg_offset, saved_reg_value; - -/* - * Proc regrdwr file write handler. - * - * This function is called when the 'regrdwr' file is opened for writing - * - * This function can be used to write to a register. - */ -static ssize_t -mwifiex_regrdwr_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); - int ret = 0; - u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; - - if (!buf) - return -ENOMEM; - - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); - - if (reg_type == 0 || reg_offset == 0) { - ret = -EINVAL; - goto done; - } else { - saved_reg_type = reg_type; - saved_reg_offset = reg_offset; - saved_reg_value = reg_value; - ret = count; - } -done: - free_page(addr); - return ret; -} - -/* - * Proc regrdwr file read handler. - * - * This function is called when the 'regrdwr' file is opened for reading - * - * This function can be used to read from a register. - */ -static ssize_t -mwifiex_regrdwr_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - int pos = 0, ret = 0; - u32 reg_value; - - if (!buf) - return -ENOMEM; - - if (!saved_reg_type) { - /* No command has been given */ - pos += snprintf(buf, PAGE_SIZE, "0"); - goto done; - } - /* Set command has been given */ - if (saved_reg_value != UINT_MAX) { - ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset, - saved_reg_value); - - pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", - saved_reg_type, saved_reg_offset, - saved_reg_value); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - - goto done; - } - /* Get command has been given */ - ret = mwifiex_reg_read(priv, saved_reg_type, - saved_reg_offset, ®_value); - if (ret) { - ret = -EINVAL; - goto done; - } - - pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type, - saved_reg_offset, reg_value); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - -done: - free_page(addr); - return ret; -} - -static u32 saved_offset = -1, saved_bytes = -1; - -/* - * Proc rdeeprom file write handler. - * - * This function is called when the 'rdeeprom' file is opened for writing - * - * This function can be used to write to a RDEEPROM location. - */ -static ssize_t -mwifiex_rdeeprom_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); - int ret = 0; - int offset = -1, bytes = -1; - - if (!buf) - return -ENOMEM; - - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - sscanf(buf, "%d %d", &offset, &bytes); - - if (offset == -1 || bytes == -1) { - ret = -EINVAL; - goto done; - } else { - saved_offset = offset; - saved_bytes = bytes; - ret = count; - } -done: - free_page(addr); - return ret; -} - -/* - * Proc rdeeprom read write handler. - * - * This function is called when the 'rdeeprom' file is opened for reading - * - * This function can be used to read from a RDEEPROM location. - */ -static ssize_t -mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - int pos = 0, ret = 0, i = 0; - u8 value[MAX_EEPROM_DATA]; - - if (!buf) - return -ENOMEM; - - if (saved_offset == -1) { - /* No command has been given */ - pos += snprintf(buf, PAGE_SIZE, "0"); - goto done; - } - - /* Get command has been given */ - ret = mwifiex_eeprom_read(priv, (u16) saved_offset, - (u16) saved_bytes, value); - if (ret) { - ret = -EINVAL; - goto done; - } - - pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); - - for (i = 0; i < saved_bytes; i++) - pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - -done: - free_page(addr); - return ret; -} - - -#define MWIFIEX_DFS_ADD_FILE(name) do { \ - if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ - priv, &mwifiex_dfs_##name##_fops)) \ - return; \ -} while (0); - -#define MWIFIEX_DFS_FILE_OPS(name) \ -static const struct file_operations mwifiex_dfs_##name##_fops = { \ - .read = mwifiex_##name##_read, \ - .write = mwifiex_##name##_write, \ - .open = mwifiex_open_generic, \ -}; - -#define MWIFIEX_DFS_FILE_READ_OPS(name) \ -static const struct file_operations mwifiex_dfs_##name##_fops = { \ - .read = mwifiex_##name##_read, \ - .open = mwifiex_open_generic, \ -}; - -#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \ -static const struct file_operations mwifiex_dfs_##name##_fops = { \ - .write = mwifiex_##name##_write, \ - .open = mwifiex_open_generic, \ -}; - - -MWIFIEX_DFS_FILE_READ_OPS(info); -MWIFIEX_DFS_FILE_READ_OPS(debug); -MWIFIEX_DFS_FILE_READ_OPS(getlog); -MWIFIEX_DFS_FILE_OPS(regrdwr); -MWIFIEX_DFS_FILE_OPS(rdeeprom); - -/* - * This function creates the debug FS directory structure and the files. - */ -void -mwifiex_dev_debugfs_init(struct mwifiex_private *priv) -{ - if (!mwifiex_dfs_dir || !priv) - return; - - priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name, - mwifiex_dfs_dir); - - if (!priv->dfs_dev_dir) - return; - - MWIFIEX_DFS_ADD_FILE(info); - MWIFIEX_DFS_ADD_FILE(debug); - MWIFIEX_DFS_ADD_FILE(getlog); - MWIFIEX_DFS_ADD_FILE(regrdwr); - MWIFIEX_DFS_ADD_FILE(rdeeprom); -} - -/* - * This function removes the debug FS directory structure and the files. - */ -void -mwifiex_dev_debugfs_remove(struct mwifiex_private *priv) -{ - if (!priv) - return; - - debugfs_remove_recursive(priv->dfs_dev_dir); -} - -/* - * This function creates the top level proc directory. - */ -void -mwifiex_debugfs_init(void) -{ - if (!mwifiex_dfs_dir) - mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL); -} - -/* - * This function removes the top level proc directory. - */ -void -mwifiex_debugfs_remove(void) -{ - if (mwifiex_dfs_dir) - debugfs_remove(mwifiex_dfs_dir); -} diff --git a/trunk/drivers/net/wireless/mwifiex/decl.h b/trunk/drivers/net/wireless/mwifiex/decl.h deleted file mode 100644 index 0e90b0986ed8..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/decl.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Marvell Wireless LAN device driver: generic data structures and APIs - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_DECL_H_ -#define _MWIFIEX_DECL_H_ - -#undef pr_fmt -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include - - -#define MWIFIEX_MAX_BSS_NUM (1) - -#define MWIFIEX_MIN_DATA_HEADER_LEN 32 /* (sizeof(mwifiex_txpd)) */ - -#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 -#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 - -#define MWIFIEX_AMPDU_DEF_TXWINSIZE 32 -#define MWIFIEX_AMPDU_DEF_RXWINSIZE 16 -#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff - -#define MWIFIEX_RATE_INDEX_HRDSSS0 0 -#define MWIFIEX_RATE_INDEX_HRDSSS3 3 -#define MWIFIEX_RATE_INDEX_OFDM0 4 -#define MWIFIEX_RATE_INDEX_OFDM7 11 -#define MWIFIEX_RATE_INDEX_MCS0 12 - -#define MWIFIEX_RATE_BITMAP_OFDM0 16 -#define MWIFIEX_RATE_BITMAP_OFDM7 23 -#define MWIFIEX_RATE_BITMAP_MCS0 32 -#define MWIFIEX_RATE_BITMAP_MCS127 159 - -#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) - -#define MWIFIEX_RTS_MIN_VALUE (0) -#define MWIFIEX_RTS_MAX_VALUE (2347) -#define MWIFIEX_FRAG_MIN_VALUE (256) -#define MWIFIEX_FRAG_MAX_VALUE (2346) - -#define MWIFIEX_SDIO_BLOCK_SIZE 256 - -#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) - -enum mwifiex_bss_type { - MWIFIEX_BSS_TYPE_STA = 0, - MWIFIEX_BSS_TYPE_UAP = 1, - MWIFIEX_BSS_TYPE_ANY = 0xff, -}; - -enum mwifiex_bss_role { - MWIFIEX_BSS_ROLE_STA = 0, - MWIFIEX_BSS_ROLE_UAP = 1, - MWIFIEX_BSS_ROLE_ANY = 0xff, -}; - -#define BSS_ROLE_BIT_MASK BIT(0) - -#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) - -enum mwifiex_data_frame_type { - MWIFIEX_DATA_FRAME_TYPE_ETH_II = 0, - MWIFIEX_DATA_FRAME_TYPE_802_11, -}; - -struct mwifiex_fw_image { - u8 *helper_buf; - u32 helper_len; - u8 *fw_buf; - u32 fw_len; -}; - -struct mwifiex_802_11_ssid { - u32 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; -}; - -struct mwifiex_wait_queue { - wait_queue_head_t wait; - u16 condition; - int status; -}; - -struct mwifiex_rxinfo { - u8 bss_index; - struct sk_buff *parent; - u8 use_count; -}; - -struct mwifiex_txinfo { - u32 status_code; - u8 flags; - u8 bss_index; -}; - -struct mwifiex_bss_attr { - u8 bss_type; - u8 frame_type; - u8 active; - u8 bss_priority; - u8 bss_num; -}; - -enum mwifiex_wmm_ac_e { - WMM_AC_BK, - WMM_AC_BE, - WMM_AC_VI, - WMM_AC_VO -} __packed; -#endif /* !_MWIFIEX_DECL_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h deleted file mode 100644 index 6d1c4545eda6..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * Marvell Wireless LAN device driver: Firmware specific macros & structures - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_FW_H_ -#define _MWIFIEX_FW_H_ - -#include - - -#define INTF_HEADER_LEN 4 - -struct rfc_1042_hdr { - u8 llc_dsap; - u8 llc_ssap; - u8 llc_ctrl; - u8 snap_oui[3]; - u16 snap_type; -}; - -struct rx_packet_hdr { - struct ethhdr eth803_hdr; - struct rfc_1042_hdr rfc1042_hdr; -}; - -struct tx_packet_hdr { - struct ethhdr eth803_hdr; - struct rfc_1042_hdr rfc1042_hdr; -}; - -#define B_SUPPORTED_RATES 5 -#define G_SUPPORTED_RATES 9 -#define BG_SUPPORTED_RATES 13 -#define A_SUPPORTED_RATES 9 -#define HOSTCMD_SUPPORTED_RATES 14 -#define N_SUPPORTED_RATES 3 -#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN) - -#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11)) -#define IS_SUPPORT_MULTI_BANDS(adapter) \ - (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) -#define GET_FW_DEFAULT_BANDS(adapter) \ - ((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS) - -extern u8 supported_rates_b[B_SUPPORTED_RATES]; -extern u8 supported_rates_g[G_SUPPORTED_RATES]; -extern u8 supported_rates_bg[BG_SUPPORTED_RATES]; -extern u8 supported_rates_a[A_SUPPORTED_RATES]; -extern u8 supported_rates_n[N_SUPPORTED_RATES]; - -#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff - -#define KEY_INFO_ENABLED 0x01 -enum KEY_TYPE_ID { - KEY_TYPE_ID_WEP = 0, - KEY_TYPE_ID_TKIP, - KEY_TYPE_ID_AES, - KEY_TYPE_ID_WAPI, -}; -#define KEY_MCAST BIT(0) -#define KEY_UNICAST BIT(1) -#define KEY_ENABLED BIT(2) - -#define WAPI_KEY_LEN 50 - -#define MAX_POLL_TRIES 100 - -#define MAX_MULTI_INTERFACE_POLL_TRIES 1000 - -#define MAX_FIRMWARE_POLL_TRIES 100 - -#define FIRMWARE_READY 0xfedc - -enum MWIFIEX_802_11_PRIVACY_FILTER { - MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, - MWIFIEX_802_11_PRIV_FILTER_8021X_WEP -}; - -enum MWIFIEX_802_11_WEP_STATUS { - MWIFIEX_802_11_WEP_ENABLED, - MWIFIEX_802_11_WEP_DISABLED, -}; - -#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) - -#define PROPRIETARY_TLV_BASE_ID 0x0100 -#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) -#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) -#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) -#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) -#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) -#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) -#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) -#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) -#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) -#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) -#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) -#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) -#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) -#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) -#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) - -#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 - -#define SSN_MASK 0xfff0 - -#define BA_RESULT_SUCCESS 0x0 -#define BA_RESULT_TIMEOUT 0x2 - -#define IS_BASTREAM_SETUP(ptr) (ptr->ba_status) - -#define BA_STREAM_NOT_ALLOWED 0xff - -#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \ - priv->adapter->config_bands & BAND_AN) \ - && priv->curr_bss_params.bss_descriptor.bcn_ht_cap) -#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\ - BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS) - -#define MWIFIEX_TX_DATA_BUF_SIZE_4K 4096 -#define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 - -#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) - -/* dev_cap bitmap - * BIT - * 0-16 reserved - * 17 IEEE80211_HT_CAP_SUP_WIDTH_20_40 - * 18-22 reserved - * 23 IEEE80211_HT_CAP_SGI_20 - * 24 IEEE80211_HT_CAP_SGI_40 - * 25 IEEE80211_HT_CAP_TX_STBC - * 26 IEEE80211_HT_CAP_RX_STBC - * 27-28 reserved - * 29 IEEE80211_HT_CAP_GRN_FLD - * 30-31 reserved - */ -#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17)) -#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) -#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) -#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) -#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) -#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) - -#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) -#define SETHT_MCS32(x) (x[4] |= 1) - -#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) - -#define LLC_SNAP_LEN 8 - -#define MOD_CLASS_HR_DSSS 0x03 -#define MOD_CLASS_OFDM 0x07 -#define MOD_CLASS_HT 0x08 -#define HT_BW_20 0 -#define HT_BW_40 1 - -#define HostCmd_CMD_GET_HW_SPEC 0x0003 -#define HostCmd_CMD_802_11_SCAN 0x0006 -#define HostCmd_CMD_802_11_GET_LOG 0x000b -#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010 -#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059 -#define HostCmd_CMD_802_11_ASSOCIATE 0x0012 -#define HostCmd_CMD_802_11_SNMP_MIB 0x0016 -#define HostCmd_CMD_MAC_REG_ACCESS 0x0019 -#define HostCmd_CMD_BBP_REG_ACCESS 0x001a -#define HostCmd_CMD_RF_REG_ACCESS 0x001b -#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad -#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d -#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 -#define HostCmd_CMD_MAC_CONTROL 0x0028 -#define HostCmd_CMD_802_11_AD_HOC_START 0x002b -#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c -#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040 -#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D -#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b -#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e -#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c -#define HostCmd_CMD_WMM_GET_STATUS 0x0071 -#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f -#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 -#define HostCmd_CMD_VERSION_EXT 0x0097 -#define HostCmd_CMD_RSSI_INFO 0x00a4 -#define HostCmd_CMD_FUNC_INIT 0x00a9 -#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa -#define HostCmd_CMD_11N_CFG 0x00cd -#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce -#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf -#define HostCmd_CMD_11N_DELBA 0x00d0 -#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 -#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df -#define HostCmd_CMD_TXPWR_CFG 0x00d1 -#define HostCmd_CMD_TX_RATE_CFG 0x00d6 -#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 -#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 -#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed -#define HostCmd_CMD_SET_BSS_MODE 0x00f7 - - -enum ENH_PS_MODES { - EN_PS = 1, - DIS_PS = 2, - EN_AUTO_DS = 3, - DIS_AUTO_DS = 4, - SLEEP_CONFIRM = 5, - GET_PS = 0, - EN_AUTO_PS = 0xff, - DIS_AUTO_PS = 0xfe, -}; - -#define HostCmd_RET_BIT 0x8000 -#define HostCmd_ACT_GEN_GET 0x0000 -#define HostCmd_ACT_GEN_SET 0x0001 -#define HostCmd_RESULT_OK 0x0000 - -#define HostCmd_ACT_MAC_RX_ON 0x0001 -#define HostCmd_ACT_MAC_TX_ON 0x0002 -#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008 -#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010 -#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 -#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 -#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000 - -#define HostCmd_BSS_MODE_IBSS 0x0002 -#define HostCmd_BSS_MODE_ANY 0x0003 - -#define HostCmd_SCAN_RADIO_TYPE_BG 0 -#define HostCmd_SCAN_RADIO_TYPE_A 1 - -#define HOST_SLEEP_CFG_CANCEL 0xffffffff -#define HOST_SLEEP_CFG_COND_DEF 0x0000000f -#define HOST_SLEEP_CFG_GPIO_DEF 0xff -#define HOST_SLEEP_CFG_GAP_DEF 0 - -#define CMD_F_HOSTCMD (1 << 0) -#define CMD_F_CANCELED (1 << 1) - -#define HostCmd_CMD_ID_MASK 0x0fff - -#define HostCmd_SEQ_NUM_MASK 0x00ff - -#define HostCmd_BSS_NUM_MASK 0x0f00 - -#define HostCmd_BSS_TYPE_MASK 0xf000 - -#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \ - (((seq) & 0x00ff) | \ - (((num) & 0x000f) << 8)) | \ - (((type) & 0x000f) << 12); } - -#define HostCmd_GET_SEQ_NO(seq) \ - ((seq) & HostCmd_SEQ_NUM_MASK) - -#define HostCmd_GET_BSS_NO(seq) \ - (((seq) & HostCmd_BSS_NUM_MASK) >> 8) - -#define HostCmd_GET_BSS_TYPE(seq) \ - (((seq) & HostCmd_BSS_TYPE_MASK) >> 12) - -#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001 -#define EVENT_LINK_LOST 0x00000003 -#define EVENT_LINK_SENSED 0x00000004 -#define EVENT_MIB_CHANGED 0x00000006 -#define EVENT_INIT_DONE 0x00000007 -#define EVENT_DEAUTHENTICATED 0x00000008 -#define EVENT_DISASSOCIATED 0x00000009 -#define EVENT_PS_AWAKE 0x0000000a -#define EVENT_PS_SLEEP 0x0000000b -#define EVENT_MIC_ERR_MULTICAST 0x0000000d -#define EVENT_MIC_ERR_UNICAST 0x0000000e -#define EVENT_DEEP_SLEEP_AWAKE 0x00000010 -#define EVENT_ADHOC_BCN_LOST 0x00000011 - -#define EVENT_WMM_STATUS_CHANGE 0x00000017 -#define EVENT_BG_SCAN_REPORT 0x00000018 -#define EVENT_RSSI_LOW 0x00000019 -#define EVENT_SNR_LOW 0x0000001a -#define EVENT_MAX_FAIL 0x0000001b -#define EVENT_RSSI_HIGH 0x0000001c -#define EVENT_SNR_HIGH 0x0000001d -#define EVENT_IBSS_COALESCED 0x0000001e -#define EVENT_DATA_RSSI_LOW 0x00000024 -#define EVENT_DATA_SNR_LOW 0x00000025 -#define EVENT_DATA_RSSI_HIGH 0x00000026 -#define EVENT_DATA_SNR_HIGH 0x00000027 -#define EVENT_LINK_QUALITY 0x00000028 -#define EVENT_PORT_RELEASE 0x0000002b -#define EVENT_PRE_BEACON_LOST 0x00000031 -#define EVENT_ADDBA 0x00000033 -#define EVENT_DELBA 0x00000034 -#define EVENT_BA_STREAM_TIEMOUT 0x00000037 -#define EVENT_AMSDU_AGGR_CTRL 0x00000042 -#define EVENT_WEP_ICV_ERR 0x00000046 -#define EVENT_HS_ACT_REQ 0x00000047 -#define EVENT_BW_CHANGE 0x00000048 - -#define EVENT_HOSTWAKE_STAIE 0x0000004d - -#define EVENT_ID_MASK 0xffff -#define BSS_NUM_MASK 0xf - -#define EVENT_GET_BSS_NUM(event_cause) \ - (((event_cause) >> 16) & BSS_NUM_MASK) - -#define EVENT_GET_BSS_TYPE(event_cause) \ - (((event_cause) >> 24) & 0x00ff) - -struct mwifiex_ie_types_header { - __le16 type; - __le16 len; -} __packed; - -struct mwifiex_ie_types_data { - struct mwifiex_ie_types_header header; - u8 data[1]; -} __packed; - -#define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 -#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 - -struct txpd { - u8 bss_type; - u8 bss_num; - __le16 tx_pkt_length; - __le16 tx_pkt_offset; - __le16 tx_pkt_type; - __le32 tx_control; - u8 priority; - u8 flags; - u8 pkt_delay_2ms; - u8 reserved1; -} __packed; - -struct rxpd { - u8 bss_type; - u8 bss_num; - u16 rx_pkt_length; - u16 rx_pkt_offset; - u16 rx_pkt_type; - u16 seq_num; - u8 priority; - u8 rx_rate; - s8 snr; - s8 nf; - /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 - * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 - * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ - u8 ht_info; - u8 reserved; -} __packed; - -enum mwifiex_chan_scan_mode_bitmasks { - MWIFIEX_PASSIVE_SCAN = BIT(0), - MWIFIEX_DISABLE_CHAN_FILT = BIT(1), -}; - -#define SECOND_CHANNEL_BELOW 0x30 -#define SECOND_CHANNEL_ABOVE 0x10 -struct mwifiex_chan_scan_param_set { - u8 radio_type; - u8 chan_number; - u8 chan_scan_mode_bitmap; - __le16 min_scan_time; - __le16 max_scan_time; -} __packed; - -struct mwifiex_ie_types_chan_list_param_set { - struct mwifiex_ie_types_header header; - struct mwifiex_chan_scan_param_set chan_scan_param[1]; -} __packed; - -struct chan_band_param_set { - u8 radio_type; - u8 chan_number; -}; - -struct mwifiex_ie_types_chan_band_list_param_set { - struct mwifiex_ie_types_header header; - struct chan_band_param_set chan_band_param[1]; -} __packed; - -struct mwifiex_ie_types_rates_param_set { - struct mwifiex_ie_types_header header; - u8 rates[1]; -} __packed; - -struct mwifiex_ie_types_ssid_param_set { - struct mwifiex_ie_types_header header; - u8 ssid[1]; -} __packed; - -struct mwifiex_ie_types_num_probes { - struct mwifiex_ie_types_header header; - __le16 num_probes; -} __packed; - -struct mwifiex_ie_types_wildcard_ssid_params { - struct mwifiex_ie_types_header header; - u8 max_ssid_length; - u8 ssid[1]; -} __packed; - -#define TSF_DATA_SIZE 8 -struct mwifiex_ie_types_tsf_timestamp { - struct mwifiex_ie_types_header header; - u8 tsf_data[1]; -} __packed; - -struct mwifiex_cf_param_set { - u8 cfp_cnt; - u8 cfp_period; - u16 cfp_max_duration; - u16 cfp_duration_remaining; -} __packed; - -struct mwifiex_ibss_param_set { - u16 atim_window; -} __packed; - -struct mwifiex_ie_types_ss_param_set { - struct mwifiex_ie_types_header header; - union { - struct mwifiex_cf_param_set cf_param_set[1]; - struct mwifiex_ibss_param_set ibss_param_set[1]; - } cf_ibss; -} __packed; - -struct mwifiex_fh_param_set { - u16 dwell_time; - u8 hop_set; - u8 hop_pattern; - u8 hop_index; -} __packed; - -struct mwifiex_ds_param_set { - u8 current_chan; -} __packed; - -struct mwifiex_ie_types_phy_param_set { - struct mwifiex_ie_types_header header; - union { - struct mwifiex_fh_param_set fh_param_set[1]; - struct mwifiex_ds_param_set ds_param_set[1]; - } fh_ds; -} __packed; - -struct mwifiex_ie_types_auth_type { - struct mwifiex_ie_types_header header; - __le16 auth_type; -} __packed; - -struct mwifiex_ie_types_vendor_param_set { - struct mwifiex_ie_types_header header; - u8 ie[MWIFIEX_MAX_VSIE_LEN]; -}; - -struct mwifiex_ie_types_rsn_param_set { - struct mwifiex_ie_types_header header; - u8 rsn_ie[1]; -} __packed; - -#define KEYPARAMSET_FIXED_LEN 6 - -struct mwifiex_ie_type_key_param_set { - __le16 type; - __le16 length; - __le16 key_type_id; - __le16 key_info; - __le16 key_len; - u8 key[50]; -} __packed; - -struct host_cmd_ds_802_11_key_material { - __le16 action; - struct mwifiex_ie_type_key_param_set key_param_set; -} __packed; - -struct host_cmd_ds_gen { - u16 command; - u16 size; - u16 seq_num; - u16 result; -}; - -#define S_DS_GEN sizeof(struct host_cmd_ds_gen) - -enum sleep_resp_ctrl { - RESP_NOT_NEEDED = 0, - RESP_NEEDED, -}; - -struct mwifiex_ps_param { - __le16 null_pkt_interval; - __le16 multiple_dtims; - __le16 bcn_miss_timeout; - __le16 local_listen_interval; - __le16 adhoc_wake_period; - __le16 mode; - __le16 delay_to_ps; -}; - -#define BITMAP_AUTO_DS 0x01 -#define BITMAP_STA_PS 0x10 - -struct mwifiex_ie_types_auto_ds_param { - struct mwifiex_ie_types_header header; - __le16 deep_sleep_timeout; -} __packed; - -struct mwifiex_ie_types_ps_param { - struct mwifiex_ie_types_header header; - struct mwifiex_ps_param param; -} __packed; - -struct host_cmd_ds_802_11_ps_mode_enh { - __le16 action; - - union { - struct mwifiex_ps_param opt_ps; - __le16 ps_bitmap; - } params; -} __packed; - -struct host_cmd_ds_get_hw_spec { - __le16 hw_if_version; - __le16 version; - __le16 reserved; - __le16 num_of_mcast_adr; - u8 permanent_addr[ETH_ALEN]; - __le16 region_code; - __le16 number_of_antenna; - __le32 fw_release_number; - __le32 reserved_1; - __le32 reserved_2; - __le32 reserved_3; - __le32 fw_cap_info; - __le32 dot_11n_dev_cap; - u8 dev_mcs_support; - __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ - __le16 reserved_4; -} __packed; - -struct host_cmd_ds_802_11_rssi_info { - __le16 action; - __le16 ndata; - __le16 nbcn; - __le16 reserved[9]; - long long reserved_1; -}; - -struct host_cmd_ds_802_11_rssi_info_rsp { - __le16 action; - __le16 ndata; - __le16 nbcn; - __le16 data_rssi_last; - __le16 data_nf_last; - __le16 data_rssi_avg; - __le16 data_nf_avg; - __le16 bcn_rssi_last; - __le16 bcn_nf_last; - __le16 bcn_rssi_avg; - __le16 bcn_nf_avg; - long long tsf_bcn; -}; - -struct host_cmd_ds_802_11_mac_address { - __le16 action; - u8 mac_addr[ETH_ALEN]; -}; - -struct host_cmd_ds_mac_control { - __le16 action; - __le16 reserved; -}; - -struct host_cmd_ds_mac_multicast_adr { - __le16 action; - __le16 num_of_adrs; - u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; -} __packed; - -struct host_cmd_ds_802_11_deauthenticate { - u8 mac_addr[ETH_ALEN]; - __le16 reason_code; -} __packed; - -struct host_cmd_ds_802_11_associate { - u8 peer_sta_addr[ETH_ALEN]; - __le16 cap_info_bitmap; - __le16 listen_interval; - __le16 beacon_period; - u8 dtim_period; -} __packed; - -struct ieee_types_assoc_rsp { - __le16 cap_info_bitmap; - __le16 status_code; - __le16 a_id; - u8 ie_buffer[1]; -} __packed; - -struct host_cmd_ds_802_11_associate_rsp { - struct ieee_types_assoc_rsp assoc_rsp; -} __packed; - -struct ieee_types_cf_param_set { - u8 element_id; - u8 len; - u8 cfp_cnt; - u8 cfp_period; - u16 cfp_max_duration; - u16 cfp_duration_remaining; -} __packed; - -struct ieee_types_ibss_param_set { - u8 element_id; - u8 len; - __le16 atim_window; -} __packed; - -union ieee_types_ss_param_set { - struct ieee_types_cf_param_set cf_param_set; - struct ieee_types_ibss_param_set ibss_param_set; -} __packed; - -struct ieee_types_fh_param_set { - u8 element_id; - u8 len; - __le16 dwell_time; - u8 hop_set; - u8 hop_pattern; - u8 hop_index; -} __packed; - -struct ieee_types_ds_param_set { - u8 element_id; - u8 len; - u8 current_chan; -} __packed; - -union ieee_types_phy_param_set { - struct ieee_types_fh_param_set fh_param_set; - struct ieee_types_ds_param_set ds_param_set; -} __packed; - -struct host_cmd_ds_802_11_ad_hoc_start { - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 bss_mode; - __le16 beacon_period; - u8 dtim_period; - union ieee_types_ss_param_set ss_param_set; - union ieee_types_phy_param_set phy_param_set; - u16 reserved1; - __le16 cap_info_bitmap; - u8 DataRate[HOSTCMD_SUPPORTED_RATES]; -} __packed; - -struct host_cmd_ds_802_11_ad_hoc_result { - u8 pad[3]; - u8 bssid[ETH_ALEN]; -} __packed; - -struct adhoc_bss_desc { - u8 bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 bss_mode; - __le16 beacon_period; - u8 dtim_period; - u8 time_stamp[8]; - u8 local_time[8]; - union ieee_types_phy_param_set phy_param_set; - union ieee_types_ss_param_set ss_param_set; - __le16 cap_info_bitmap; - u8 data_rates[HOSTCMD_SUPPORTED_RATES]; - - /* - * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. - * It is used in the Adhoc join command and will cause a - * binary layout mismatch with the firmware - */ -} __packed; - -struct host_cmd_ds_802_11_ad_hoc_join { - struct adhoc_bss_desc bss_descriptor; - u16 reserved1; - u16 reserved2; -} __packed; - -struct host_cmd_ds_802_11_get_log { - __le32 mcast_tx_frame; - __le32 failed; - __le32 retry; - __le32 multi_retry; - __le32 frame_dup; - __le32 rts_success; - __le32 rts_failure; - __le32 ack_failure; - __le32 rx_frag; - __le32 mcast_rx_frame; - __le32 fcs_error; - __le32 tx_frame; - __le32 reserved; - __le32 wep_icv_err_cnt[4]; -}; - -struct host_cmd_ds_tx_rate_query { - u8 tx_rate; - /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 - * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 - * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ - u8 ht_info; -} __packed; - -enum Host_Sleep_Action { - HS_CONFIGURE = 0x0001, - HS_ACTIVATE = 0x0002, -}; - -struct mwifiex_hs_config_param { - __le32 conditions; - u8 gpio; - u8 gap; -} __packed; - -struct hs_activate_param { - u16 resp_ctrl; -} __packed; - -struct host_cmd_ds_802_11_hs_cfg_enh { - __le16 action; - - union { - struct mwifiex_hs_config_param hs_config; - struct hs_activate_param hs_activate; - } params; -} __packed; - -enum SNMP_MIB_INDEX { - OP_RATE_SET_I = 1, - DTIM_PERIOD_I = 3, - RTS_THRESH_I = 5, - SHORT_RETRY_LIM_I = 6, - LONG_RETRY_LIM_I = 7, - FRAG_THRESH_I = 8, - DOT11D_I = 9, -}; - -#define MAX_SNMP_BUF_SIZE 128 - -struct host_cmd_ds_802_11_snmp_mib { - __le16 query_type; - __le16 oid; - __le16 buf_size; - u8 value[1]; -} __packed; - -struct mwifiex_rate_scope { - __le16 type; - __le16 length; - __le16 hr_dsss_rate_bitmap; - __le16 ofdm_rate_bitmap; - __le16 ht_mcs_rate_bitmap[8]; -} __packed; - -struct mwifiex_rate_drop_pattern { - __le16 type; - __le16 length; - __le32 rate_drop_mode; -} __packed; - -struct host_cmd_ds_tx_rate_cfg { - __le16 action; - __le16 cfg_index; -} __packed; - -struct mwifiex_power_group { - u8 modulation_class; - u8 first_rate_code; - u8 last_rate_code; - s8 power_step; - s8 power_min; - s8 power_max; - u8 ht_bandwidth; - u8 reserved; -} __packed; - -struct mwifiex_types_power_group { - u16 type; - u16 length; -} __packed; - -struct host_cmd_ds_txpwr_cfg { - __le16 action; - __le16 cfg_index; - __le32 mode; -} __packed; - -#define MWIFIEX_USER_SCAN_CHAN_MAX 50 - -#define MWIFIEX_MAX_SSID_LIST_LENGTH 10 - -struct mwifiex_scan_cmd_config { - /* - * BSS Type to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. Valid settings are: - * - * - MWIFIEX_SCAN_MODE_BSS (infrastructure) - * - MWIFIEX_SCAN_MODE_IBSS (adhoc) - * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) - */ - u8 bss_mode; - - /* Specific BSSID used to filter scan results in the firmware */ - u8 specific_bssid[ETH_ALEN]; - - /* Length of TLVs sent in command starting at tlvBuffer */ - u32 tlv_buf_len; - - /* - * SSID TLV(s) and ChanList TLVs to be sent in the firmware command - * - * TLV_TYPE_CHANLIST, mwifiex_ie_types_chan_list_param_set - * WLAN_EID_SSID, mwifiex_ie_types_ssid_param_set - */ - u8 tlv_buf[1]; /* SSID TLV(s) and ChanList TLVs are stored - here */ -} __packed; - -struct mwifiex_user_scan_chan { - u8 chan_number; - u8 radio_type; - u8 scan_type; - u8 reserved; - u32 scan_time; -} __packed; - -struct mwifiex_user_scan_ssid { - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 max_len; -} __packed; - -struct mwifiex_user_scan_cfg { - /* - * Flag set to keep the previous scan table intact - * - * If set, the scan results will accumulate, replacing any previous - * matched entries for a BSS with the new scan data - */ - u8 keep_previous_scan; - /* - * BSS mode to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. Valid settings are: - * - * - MWIFIEX_SCAN_MODE_BSS (infrastructure) - * - MWIFIEX_SCAN_MODE_IBSS (adhoc) - * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) - */ - u8 bss_mode; - /* Configure the number of probe requests for active chan scans */ - u8 num_probes; - u8 reserved; - /* BSSID filter sent in the firmware command to limit the results */ - u8 specific_bssid[ETH_ALEN]; - /* SSID filter list used in the to limit the scan results */ - struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH]; - /* Variable number (fixed maximum) of channels to scan up */ - struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX]; -} __packed; - -struct ie_body { - u8 grp_key_oui[4]; - u8 ptk_cnt[2]; - u8 ptk_body[4]; -} __packed; - -struct host_cmd_ds_802_11_scan { - u8 bss_mode; - u8 bssid[ETH_ALEN]; - u8 tlv_buffer[1]; -} __packed; - -struct host_cmd_ds_802_11_scan_rsp { - __le16 bss_descript_size; - u8 number_of_sets; - u8 bss_desc_and_tlv_buffer[1]; -} __packed; - -struct host_cmd_ds_802_11_bg_scan_query { - u8 flush; -} __packed; - -struct host_cmd_ds_802_11_bg_scan_query_rsp { - u32 report_condition; - struct host_cmd_ds_802_11_scan_rsp scan_resp; -} __packed; - -struct mwifiex_ietypes_domain_param_set { - struct mwifiex_ie_types_header header; - u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; - struct ieee80211_country_ie_triplet triplet[1]; -} __packed; - -struct host_cmd_ds_802_11d_domain_info { - __le16 action; - struct mwifiex_ietypes_domain_param_set domain; -} __packed; - -struct host_cmd_ds_802_11d_domain_info_rsp { - __le16 action; - struct mwifiex_ietypes_domain_param_set domain; -} __packed; - -struct host_cmd_ds_11n_addba_req { - u8 add_req_result; - u8 peer_mac_addr[ETH_ALEN]; - u8 dialog_token; - __le16 block_ack_param_set; - __le16 block_ack_tmo; - __le16 ssn; -} __packed; - -struct host_cmd_ds_11n_addba_rsp { - u8 add_rsp_result; - u8 peer_mac_addr[ETH_ALEN]; - u8 dialog_token; - __le16 status_code; - __le16 block_ack_param_set; - __le16 block_ack_tmo; - __le16 ssn; -} __packed; - -struct host_cmd_ds_11n_delba { - u8 del_result; - u8 peer_mac_addr[ETH_ALEN]; - __le16 del_ba_param_set; - __le16 reason_code; - u8 reserved; -} __packed; - -struct host_cmd_ds_11n_batimeout { - u8 tid; - u8 peer_mac_addr[ETH_ALEN]; - u8 origninator; -} __packed; - -struct host_cmd_ds_11n_cfg { - __le16 action; - __le16 ht_tx_cap; - __le16 ht_tx_info; -} __packed; - -struct host_cmd_ds_txbuf_cfg { - __le16 action; - __le16 buff_size; - __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ - __le16 reserved3; -} __packed; - -struct host_cmd_ds_amsdu_aggr_ctrl { - __le16 action; - __le16 enable; - __le16 curr_buf_size; -} __packed; - -struct mwifiex_ie_types_wmm_param_set { - struct mwifiex_ie_types_header header; - u8 wmm_ie[1]; -}; - -struct mwifiex_ie_types_wmm_queue_status { - struct mwifiex_ie_types_header header; - u8 queue_index; - u8 disabled; - u16 medium_time; - u8 flow_required; - u8 flow_created; - u32 reserved; -}; - -struct ieee_types_vendor_header { - u8 element_id; - u8 len; - u8 oui[3]; - u8 oui_type; - u8 oui_subtype; - u8 version; -} __packed; - -struct ieee_types_wmm_ac_parameters { - u8 aci_aifsn_bitmap; - u8 ecw_bitmap; - __le16 tx_op_limit; -} __packed; - -struct ieee_types_wmm_parameter { - /* - * WMM Parameter IE - Vendor Specific Header: - * element_id [221/0xdd] - * Len [24] - * Oui [00:50:f2] - * OuiType [2] - * OuiSubType [1] - * Version [1] - */ - struct ieee_types_vendor_header vend_hdr; - u8 qos_info_bitmap; - u8 reserved; - struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_MAX_QUEUES]; -} __packed; - -struct ieee_types_wmm_info { - - /* - * WMM Info IE - Vendor Specific Header: - * element_id [221/0xdd] - * Len [7] - * Oui [00:50:f2] - * OuiType [2] - * OuiSubType [0] - * Version [1] - */ - struct ieee_types_vendor_header vend_hdr; - - u8 qos_info_bitmap; -} __packed; - -struct host_cmd_ds_wmm_get_status { - u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) * - IEEE80211_MAX_QUEUES]; - u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; -} __packed; - -struct mwifiex_wmm_ac_status { - u8 disabled; - u8 flow_required; - u8 flow_created; -}; - -struct mwifiex_ie_types_htcap { - struct mwifiex_ie_types_header header; - struct ieee80211_ht_cap ht_cap; -} __packed; - -struct mwifiex_ie_types_htinfo { - struct mwifiex_ie_types_header header; - struct ieee80211_ht_info ht_info; -} __packed; - -struct mwifiex_ie_types_2040bssco { - struct mwifiex_ie_types_header header; - u8 bss_co_2040; -} __packed; - -struct mwifiex_ie_types_extcap { - struct mwifiex_ie_types_header header; - u8 ext_cap; -} __packed; - -struct host_cmd_ds_mac_reg_access { - __le16 action; - __le16 offset; - __le32 value; -} __packed; - -struct host_cmd_ds_bbp_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; - -struct host_cmd_ds_rf_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; - -struct host_cmd_ds_pmic_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; - -struct host_cmd_ds_802_11_eeprom_access { - __le16 action; - - __le16 offset; - __le16 byte_count; - u8 value; -} __packed; - -struct host_cmd_ds_802_11_rf_channel { - __le16 action; - __le16 current_channel; - __le16 rf_type; - __le16 reserved; - u8 reserved_1[32]; -} __packed; - -struct host_cmd_ds_version_ext { - u8 version_str_sel; - char version_str[128]; -} __packed; - -struct host_cmd_ds_802_11_ibss_status { - __le16 action; - __le16 enable; - u8 bssid[ETH_ALEN]; - __le16 beacon_interval; - __le16 atim_window; - __le16 use_g_rate_protect; -} __packed; - -#define CONNECTION_TYPE_INFRA 0 -#define CONNECTION_TYPE_ADHOC 1 - -struct host_cmd_ds_set_bss_mode { - u8 con_type; -} __packed; - -struct host_cmd_ds_command { - __le16 command; - __le16 size; - __le16 seq_num; - __le16 result; - union { - struct host_cmd_ds_get_hw_spec hw_spec; - struct host_cmd_ds_mac_control mac_ctrl; - struct host_cmd_ds_802_11_mac_address mac_addr; - struct host_cmd_ds_mac_multicast_adr mc_addr; - struct host_cmd_ds_802_11_get_log get_log; - struct host_cmd_ds_802_11_rssi_info rssi_info; - struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp; - struct host_cmd_ds_802_11_snmp_mib smib; - struct host_cmd_ds_802_11_rf_channel rf_channel; - struct host_cmd_ds_tx_rate_query tx_rate; - struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; - struct host_cmd_ds_txpwr_cfg txp_cfg; - struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; - struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; - struct host_cmd_ds_802_11_scan scan; - struct host_cmd_ds_802_11_scan_rsp scan_resp; - struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; - struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; - struct host_cmd_ds_802_11_associate associate; - struct host_cmd_ds_802_11_associate_rsp associate_rsp; - struct host_cmd_ds_802_11_deauthenticate deauth; - struct host_cmd_ds_802_11_ad_hoc_start adhoc_start; - struct host_cmd_ds_802_11_ad_hoc_result adhoc_result; - struct host_cmd_ds_802_11_ad_hoc_join adhoc_join; - struct host_cmd_ds_802_11d_domain_info domain_info; - struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp; - struct host_cmd_ds_11n_addba_req add_ba_req; - struct host_cmd_ds_11n_addba_rsp add_ba_rsp; - struct host_cmd_ds_11n_delba del_ba; - struct host_cmd_ds_txbuf_cfg tx_buf; - struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl; - struct host_cmd_ds_11n_cfg htcfg; - struct host_cmd_ds_wmm_get_status get_wmm_status; - struct host_cmd_ds_802_11_key_material key_material; - struct host_cmd_ds_version_ext verext; - struct host_cmd_ds_802_11_ibss_status ibss_coalescing; - struct host_cmd_ds_mac_reg_access mac_reg; - struct host_cmd_ds_bbp_reg_access bbp_reg; - struct host_cmd_ds_rf_reg_access rf_reg; - struct host_cmd_ds_pmic_reg_access pmic_reg; - struct host_cmd_ds_set_bss_mode bss_mode; - struct host_cmd_ds_802_11_eeprom_access eeprom; - } params; -} __packed; - -struct mwifiex_opt_sleep_confirm { - __le16 command; - __le16 size; - __le16 seq_num; - __le16 result; - __le16 action; - __le16 resp_ctrl; -} __packed; - -struct mwifiex_opt_sleep_confirm_buffer { - u8 hdr[4]; - struct mwifiex_opt_sleep_confirm ps_cfm_sleep; -} __packed; -#endif /* !_MWIFIEX_FW_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/init.c b/trunk/drivers/net/wireless/mwifiex/init.c deleted file mode 100644 index fc2c0c5728d9..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/init.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Marvell Wireless LAN device driver: HW/FW Initialization - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * This function adds a BSS priority table to the table list. - * - * The function allocates a new BSS priority table node and adds it to - * the end of BSS priority table list, kept in driver memory. - */ -static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_node *bss_prio; - unsigned long flags; - - bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); - if (!bss_prio) { - dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", - __func__); - return -1; - } - - bss_prio->priv = priv; - INIT_LIST_HEAD(&bss_prio->list); - if (!adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur) - adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = - bss_prio; - - spin_lock_irqsave(&adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_lock, flags); - list_add_tail(&bss_prio->list, - &adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_head); - spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_lock, flags); - - return 0; -} - -/* - * This function initializes the private structure and sets default - * values to the members. - * - * Additionally, it also initializes all the locks and sets up all the - * lists. - */ -static int mwifiex_init_priv(struct mwifiex_private *priv) -{ - u32 i; - - priv->media_connected = false; - memset(priv->curr_addr, 0xff, ETH_ALEN); - - priv->pkt_tx_ctrl = 0; - priv->bss_mode = NL80211_IFTYPE_STATION; - priv->data_rate = 0; /* Initially indicate the rate as auto */ - priv->is_data_rate_auto = true; - priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; - priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; - - priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; - priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - priv->sec_info.encryption_mode = 0; - for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) - memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key)); - priv->wep_key_curr_index = 0; - priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON | - HostCmd_ACT_MAC_ETHERNETII_ENABLE; - - priv->beacon_period = 100; /* beacon interval */ ; - priv->attempted_bss_desc = NULL; - memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params)); - priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL; - - memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid)); - memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid)); - memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); - priv->assoc_rsp_size = 0; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - priv->atim_window = 0; - priv->adhoc_state = ADHOC_IDLE; - priv->tx_power_level = 0; - priv->max_tx_power_level = 0; - priv->min_tx_power_level = 0; - priv->tx_rate = 0; - priv->rxpd_htinfo = 0; - priv->rxpd_rate = 0; - priv->rate_bitmap = 0; - priv->data_rssi_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->data_nf_last = 0; - priv->bcn_rssi_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - priv->bcn_nf_last = 0; - memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie)); - memset(&priv->aes_key, 0, sizeof(priv->aes_key)); - priv->wpa_ie_len = 0; - priv->wpa_is_gtk_set = false; - - memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf)); - priv->assoc_tlv_buf_len = 0; - memset(&priv->wps, 0, sizeof(priv->wps)); - memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); - priv->gen_ie_buf_len = 0; - memset(priv->vs_ie, 0, sizeof(priv->vs_ie)); - - priv->wmm_required = true; - priv->wmm_enabled = false; - priv->wmm_qosinfo = 0; - priv->curr_bcn_buf = NULL; - priv->curr_bcn_size = 0; - - priv->scan_block = false; - - return mwifiex_add_bss_prio_tbl(priv); -} - -/* - * This function allocates buffers for members of the adapter - * structure. - * - * The memory allocated includes scan table, command buffers, and - * sleep confirm command buffer. In addition, the queues are - * also initialized. - */ -static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) -{ - int ret = 0; - u32 buf_size; - struct mwifiex_bssdescriptor *temp_scan_table; - - /* Allocate buffer to store the BSSID list */ - buf_size = sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP; - temp_scan_table = kzalloc(buf_size, GFP_KERNEL); - if (!temp_scan_table) { - dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", - __func__); - return -1; - } - - adapter->scan_table = temp_scan_table; - - /* Allocate command buffer */ - ret = mwifiex_alloc_cmd_buffer(adapter); - if (ret) { - dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n", - __func__); - return -1; - } - - adapter->sleep_cfm = - dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm_buffer) - + INTF_HEADER_LEN); - - if (!adapter->sleep_cfm) { - dev_err(adapter->dev, "%s: failed to alloc sleep cfm" - " cmd buffer\n", __func__); - return -1; - } - skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN); - - return 0; -} - -/* - * This function initializes the adapter structure and sets default - * values to the members of adapter. - * - * This also initializes the WMM related parameters in the driver private - * structures. - */ -static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) -{ - struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = NULL; - - skb_put(adapter->sleep_cfm, sizeof(sleep_cfm_buf->ps_cfm_sleep)); - sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm_buffer *) - (adapter->sleep_cfm->data); - - adapter->cmd_sent = false; - adapter->data_sent = true; - adapter->cmd_resp_received = false; - adapter->event_received = false; - adapter->data_received = false; - - adapter->surprise_removed = false; - - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - adapter->ps_state = PS_STATE_AWAKE; - adapter->need_to_wakeup = false; - - adapter->scan_mode = HostCmd_BSS_MODE_ANY; - adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME; - adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME; - adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME; - - adapter->num_in_scan_table = 0; - memset(adapter->scan_table, 0, - (sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP)); - adapter->scan_probes = 1; - - memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf)); - adapter->bcn_buf_end = adapter->bcn_buf; - - adapter->multiple_dtim = 1; - - adapter->local_listen_interval = 0; /* default value in firmware - will be used */ - - adapter->is_deep_sleep = false; - - adapter->delay_null_pkt = false; - adapter->delay_to_ps = 1000; - adapter->enhanced_ps_mode = PS_MODE_AUTO; - - adapter->gen_null_pkt = false; /* Disable NULL Pkg generation by - default */ - adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by - default */ - adapter->pm_wakeup_card_req = false; - - adapter->pm_wakeup_fw_try = false; - - adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - - adapter->is_hs_configured = false; - adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); - adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; - adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; - adapter->hs_activated = false; - - memset(adapter->event_body, 0, sizeof(adapter->event_body)); - adapter->hw_dot_11n_dev_cap = 0; - adapter->hw_dev_mcs_support = 0; - adapter->chan_offset = 0; - adapter->adhoc_11n_enabled = false; - - mwifiex_wmm_init(adapter); - - if (adapter->sleep_cfm) { - memset(&sleep_cfm_buf->ps_cfm_sleep, 0, - adapter->sleep_cfm->len); - sleep_cfm_buf->ps_cfm_sleep.command = - cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); - sleep_cfm_buf->ps_cfm_sleep.size = - cpu_to_le16(adapter->sleep_cfm->len); - sleep_cfm_buf->ps_cfm_sleep.result = 0; - sleep_cfm_buf->ps_cfm_sleep.action = cpu_to_le16(SLEEP_CONFIRM); - sleep_cfm_buf->ps_cfm_sleep.resp_ctrl = - cpu_to_le16(RESP_NEEDED); - } - memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); - memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); - adapter->tx_lock_flag = false; - adapter->null_pkt_interval = 0; - adapter->fw_bands = 0; - adapter->config_bands = 0; - adapter->adhoc_start_band = 0; - adapter->scan_channels = NULL; - adapter->fw_release_number = 0; - adapter->fw_cap_info = 0; - memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); - adapter->event_cause = 0; - adapter->region_code = 0; - adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; - adapter->adhoc_awake_period = 0; - memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); - adapter->arp_filter_size = 0; -} - -/* - * This function frees the adapter structure. - * - * The freeing operation is done recursively, by canceling all - * pending commands, freeing the member buffers previously - * allocated (command buffers, scan table buffer, sleep confirm - * command buffer), stopping the timers and calling the cleanup - * routines for every interface, before the actual adapter - * structure is freed. - */ -static void -mwifiex_free_adapter(struct mwifiex_adapter *adapter) -{ - if (!adapter) { - pr_err("%s: adapter is NULL\n", __func__); - return; - } - - mwifiex_cancel_all_pending_cmd(adapter); - - /* Free lock variables */ - mwifiex_free_lock_list(adapter); - - /* Free command buffer */ - dev_dbg(adapter->dev, "info: free cmd buffer\n"); - mwifiex_free_cmd_buffer(adapter); - - del_timer(&adapter->cmd_timer); - - dev_dbg(adapter->dev, "info: free scan table\n"); - kfree(adapter->scan_table); - adapter->scan_table = NULL; - - adapter->if_ops.cleanup_if(adapter); - - dev_kfree_skb_any(adapter->sleep_cfm); -} - -/* - * This function intializes the lock variables and - * the list heads. - */ -int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv = NULL; - s32 i = 0; - u32 j = 0; - - spin_lock_init(&adapter->mwifiex_lock); - spin_lock_init(&adapter->int_lock); - spin_lock_init(&adapter->main_proc_lock); - spin_lock_init(&adapter->mwifiex_cmd_lock); - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - spin_lock_init(&priv->rx_pkt_lock); - spin_lock_init(&priv->wmm.ra_list_spinlock); - spin_lock_init(&priv->curr_bcn_buf_lock); - } - } - - /* Initialize cmd_free_q */ - INIT_LIST_HEAD(&adapter->cmd_free_q); - /* Initialize cmd_pending_q */ - INIT_LIST_HEAD(&adapter->cmd_pending_q); - /* Initialize scan_pending_q */ - INIT_LIST_HEAD(&adapter->scan_pending_q); - - spin_lock_init(&adapter->cmd_free_q_lock); - spin_lock_init(&adapter->cmd_pending_q_lock); - spin_lock_init(&adapter->scan_pending_q_lock); - - for (i = 0; i < adapter->priv_num; ++i) { - INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); - adapter->bss_prio_tbl[i].bss_prio_cur = NULL; - spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); - } - - for (i = 0; i < adapter->priv_num; i++) { - if (!adapter->priv[i]) - continue; - priv = adapter->priv[i]; - for (j = 0; j < MAX_NUM_TID; ++j) { - INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); - spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock); - } - INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); - INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); - - spin_lock_init(&priv->tx_ba_stream_tbl_lock); - spin_lock_init(&priv->rx_reorder_tbl_lock); - } - - return 0; -} - -/* - * This function releases the lock variables and frees the locks and - * associated locks. - */ -void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv = NULL; - s32 i = 0; - s32 j = 0; - - /* Free lists */ - list_del(&adapter->cmd_free_q); - list_del(&adapter->cmd_pending_q); - list_del(&adapter->scan_pending_q); - - for (i = 0; i < adapter->priv_num; i++) - list_del(&adapter->bss_prio_tbl[i].bss_prio_head); - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - for (j = 0; j < MAX_NUM_TID; ++j) - list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); - list_del(&priv->tx_ba_stream_tbl_ptr); - list_del(&priv->rx_reorder_tbl_ptr); - } - } -} - -/* - * This function initializes the firmware. - * - * The following operations are performed sequentially - - * - Allocate adapter structure - * - Initialize the adapter structure - * - Initialize the private structure - * - Add BSS priority tables to the adapter structure - * - For each interface, send the init commands to firmware - * - Send the first command in command pending queue, if available - */ -int mwifiex_init_fw(struct mwifiex_adapter *adapter) -{ - int ret = 0; - struct mwifiex_private *priv = NULL; - u8 i = 0; - u8 first_sta = true; - int is_cmd_pend_q_empty; - unsigned long flags; - - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - - /* Allocate memory for member of adapter structure */ - ret = mwifiex_allocate_adapter(adapter); - if (ret) - return -1; - - /* Initialize adapter structure */ - mwifiex_init_adapter(adapter); - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - - /* Initialize private structure */ - ret = mwifiex_init_priv(priv); - if (ret) - return -1; - } - } - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); - if (ret == -1) - return -1; - - first_sta = false; - } - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - if (!is_cmd_pend_q_empty) { - /* Send the first command in queue and return */ - if (mwifiex_main_process(adapter) != -1) - ret = -EINPROGRESS; - } else { - adapter->hw_status = MWIFIEX_HW_STATUS_READY; - } - - return ret; -} - -/* - * This function deletes the BSS priority tables. - * - * The function traverses through all the allocated BSS priority nodes - * in every BSS priority table and frees them. - */ -static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) -{ - int i; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_node *bssprio_node = NULL, *tmp_node = NULL, - **cur = NULL; - struct list_head *head; - spinlock_t *lock; - unsigned long flags; - - for (i = 0; i < adapter->priv_num; ++i) { - head = &adapter->bss_prio_tbl[i].bss_prio_head; - cur = &adapter->bss_prio_tbl[i].bss_prio_cur; - lock = &adapter->bss_prio_tbl[i].bss_prio_lock; - dev_dbg(adapter->dev, "info: delete BSS priority table," - " index = %d, i = %d, head = %p, cur = %p\n", - priv->bss_index, i, head, *cur); - if (*cur) { - spin_lock_irqsave(lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(lock, flags); - continue; - } - bssprio_node = list_first_entry(head, - struct mwifiex_bss_prio_node, list); - spin_unlock_irqrestore(lock, flags); - - list_for_each_entry_safe(bssprio_node, tmp_node, head, - list) { - if (bssprio_node->priv == priv) { - dev_dbg(adapter->dev, "info: Delete " - "node %p, next = %p\n", - bssprio_node, tmp_node); - spin_lock_irqsave(lock, flags); - list_del(&bssprio_node->list); - spin_unlock_irqrestore(lock, flags); - kfree(bssprio_node); - } - } - *cur = (struct mwifiex_bss_prio_node *)head; - } - } -} - -/* - * This function is used to shutdown the driver. - * - * The following operations are performed sequentially - - * - Check if already shut down - * - Make sure the main process has stopped - * - Clean up the Tx and Rx queues - * - Delete BSS priority tables - * - Free the adapter - * - Notify completion - */ -int -mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) -{ - int ret = -EINPROGRESS; - struct mwifiex_private *priv = NULL; - s32 i = 0; - unsigned long flags; - - /* mwifiex already shutdown */ - if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) - return 0; - - adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING; - /* wait for mwifiex_process to complete */ - if (adapter->mwifiex_processing) { - dev_warn(adapter->dev, "main process is still running\n"); - return ret; - } - - /* shut down mwifiex */ - dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); - - /* Clean up Tx/Rx queues and delete BSS priority table */ - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - - mwifiex_clean_txrx(priv); - mwifiex_delete_bss_prio_tbl(priv); - } - } - - spin_lock_irqsave(&adapter->mwifiex_lock, flags); - - /* Free adapter structure */ - mwifiex_free_adapter(adapter); - - spin_unlock_irqrestore(&adapter->mwifiex_lock, flags); - - /* Notify completion */ - ret = mwifiex_shutdown_fw_complete(adapter); - - return ret; -} - -/* - * This function downloads the firmware to the card. - * - * The actual download is preceded by two sanity checks - - * - Check if firmware is already running - * - Check if the interface is the winner to download the firmware - * - * ...and followed by another - - * - Check if the firmware is downloaded successfully - * - * After download is successfully completed, the host interrupts are enabled. - */ -int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *pmfw) -{ - int ret = 0; - u32 poll_num = 1; - int winner; - - /* Check if firmware is already running */ - ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); - if (!ret) { - dev_notice(adapter->dev, - "WLAN FW already running! Skip FW download\n"); - goto done; - } - poll_num = MAX_FIRMWARE_POLL_TRIES; - - /* Check if we are the winner for downloading FW */ - if (!winner) { - dev_notice(adapter->dev, - "Other interface already running!" - " Skip FW download\n"); - poll_num = MAX_MULTI_INTERFACE_POLL_TRIES; - goto poll_fw; - } - if (pmfw) { - /* Download firmware with helper */ - ret = adapter->if_ops.prog_fw(adapter, pmfw); - if (ret) { - dev_err(adapter->dev, "prog_fw failed ret=%#x\n", ret); - return ret; - } - } - -poll_fw: - /* Check if the firmware is downloaded successfully or not */ - ret = adapter->if_ops.check_fw_status(adapter, poll_num, NULL); - if (ret) { - dev_err(adapter->dev, "FW failed to be active in time\n"); - return -1; - } -done: - /* re-enable host interrupt for mwifiex after fw dnld is successful */ - adapter->if_ops.enable_int(adapter); - return ret; -} diff --git a/trunk/drivers/net/wireless/mwifiex/ioctl.h b/trunk/drivers/net/wireless/mwifiex/ioctl.h deleted file mode 100644 index 5488e111fd2c..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/ioctl.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Marvell Wireless LAN device driver: ioctl data structures & APIs - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_IOCTL_H_ -#define _MWIFIEX_IOCTL_H_ - -#include - -enum { - MWIFIEX_SCAN_MODE_UNCHANGED = 0, - MWIFIEX_SCAN_MODE_BSS, - MWIFIEX_SCAN_MODE_IBSS, - MWIFIEX_SCAN_MODE_ANY -}; - -enum { - MWIFIEX_SCAN_TYPE_UNCHANGED = 0, - MWIFIEX_SCAN_TYPE_ACTIVE, - MWIFIEX_SCAN_TYPE_PASSIVE -}; - -struct mwifiex_get_scan_table_fixed { - u8 bssid[ETH_ALEN]; - u8 channel; - u8 rssi; - long long network_tsf; -}; - -struct mwifiex_scan_time_params { - u32 specific_scan_time; - u32 active_scan_time; - u32 passive_scan_time; -}; - -struct mwifiex_user_scan { - u32 scan_cfg_len; - u8 scan_cfg_buf[1]; -}; - -struct mwifiex_scan_req { - u32 scan_mode; - u32 scan_type; - struct mwifiex_802_11_ssid scan_ssid; - struct mwifiex_scan_time_params scan_time; - struct mwifiex_user_scan user_scan; -}; - -struct mwifiex_scan_resp { - u32 num_in_scan_table; - u8 *scan_table; -}; - -#define MWIFIEX_PROMISC_MODE 1 -#define MWIFIEX_MULTICAST_MODE 2 -#define MWIFIEX_ALL_MULTI_MODE 4 -#define MWIFIEX_MAX_MULTICAST_LIST_SIZE 32 - -struct mwifiex_multicast_list { - u32 mode; - u32 num_multicast_addr; - u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; -}; - -#define MWIFIEX_MAX_CHANNEL_NUM 128 - -struct mwifiex_chan_freq { - u32 channel; - u32 freq; -}; - -struct mwifiex_chan_list { - u32 num_of_chan; - struct mwifiex_chan_freq cf[MWIFIEX_MAX_CHANNEL_NUM]; -}; - -struct mwifiex_ssid_bssid { - struct mwifiex_802_11_ssid ssid; - u8 bssid[ETH_ALEN]; -}; - -enum { - BAND_B = 1, - BAND_G = 2, - BAND_A = 4, - BAND_GN = 8, - BAND_AN = 16, -}; - -#define NO_SEC_CHANNEL 0 -#define SEC_CHANNEL_ABOVE 1 -#define SEC_CHANNEL_BELOW 3 - -struct mwifiex_ds_band_cfg { - u32 config_bands; - u32 adhoc_start_band; - u32 adhoc_channel; - u32 sec_chan_offset; -}; - -enum { - ADHOC_IDLE, - ADHOC_STARTED, - ADHOC_JOINED, - ADHOC_COALESCED -}; - -struct mwifiex_ds_get_stats { - u32 mcast_tx_frame; - u32 failed; - u32 retry; - u32 multi_retry; - u32 frame_dup; - u32 rts_success; - u32 rts_failure; - u32 ack_failure; - u32 rx_frag; - u32 mcast_rx_frame; - u32 fcs_error; - u32 tx_frame; - u32 wep_icv_error[4]; -}; - -#define BCN_RSSI_LAST_MASK 0x00000001 -#define BCN_RSSI_AVG_MASK 0x00000002 -#define DATA_RSSI_LAST_MASK 0x00000004 -#define DATA_RSSI_AVG_MASK 0x00000008 -#define BCN_SNR_LAST_MASK 0x00000010 -#define BCN_SNR_AVG_MASK 0x00000020 -#define DATA_SNR_LAST_MASK 0x00000040 -#define DATA_SNR_AVG_MASK 0x00000080 -#define BCN_NF_LAST_MASK 0x00000100 -#define BCN_NF_AVG_MASK 0x00000200 -#define DATA_NF_LAST_MASK 0x00000400 -#define DATA_NF_AVG_MASK 0x00000800 -#define ALL_RSSI_INFO_MASK 0x00000fff - -struct mwifiex_ds_get_signal { - /* - * Bit0: Last Beacon RSSI, Bit1: Average Beacon RSSI, - * Bit2: Last Data RSSI, Bit3: Average Data RSSI, - * Bit4: Last Beacon SNR, Bit5: Average Beacon SNR, - * Bit6: Last Data SNR, Bit7: Average Data SNR, - * Bit8: Last Beacon NF, Bit9: Average Beacon NF, - * Bit10: Last Data NF, Bit11: Average Data NF - */ - u16 selector; - s16 bcn_rssi_last; - s16 bcn_rssi_avg; - s16 data_rssi_last; - s16 data_rssi_avg; - s16 bcn_snr_last; - s16 bcn_snr_avg; - s16 data_snr_last; - s16 data_snr_avg; - s16 bcn_nf_last; - s16 bcn_nf_avg; - s16 data_nf_last; - s16 data_nf_avg; -}; - -struct mwifiex_fw_info { - u32 fw_ver; - u8 mac_addr[ETH_ALEN]; -}; - -#define MWIFIEX_MAX_VER_STR_LEN 128 - -struct mwifiex_ver_ext { - u32 version_str_sel; - char version_str[MWIFIEX_MAX_VER_STR_LEN]; -}; - -struct mwifiex_bss_info { - u32 bss_mode; - struct mwifiex_802_11_ssid ssid; - u32 scan_table_idx; - u32 bss_chan; - u32 region_code; - u32 media_connected; - u32 max_power_level; - u32 min_power_level; - u32 adhoc_state; - signed int bcn_nf_last; - u32 wep_status; - u32 is_hs_configured; - u32 is_deep_sleep; - u8 bssid[ETH_ALEN]; -}; - -#define MAX_NUM_TID 8 - -#define MAX_RX_WINSIZE 64 - -struct mwifiex_ds_rx_reorder_tbl { - u16 tid; - u8 ta[ETH_ALEN]; - u32 start_win; - u32 win_size; - u32 buffer[MAX_RX_WINSIZE]; -}; - -struct mwifiex_ds_tx_ba_stream_tbl { - u16 tid; - u8 ra[ETH_ALEN]; -}; - -#define DBG_CMD_NUM 5 - -struct mwifiex_debug_info { - u32 int_counter; - u32 packets_out[MAX_NUM_TID]; - u32 max_tx_buf_size; - u32 tx_buf_size; - u32 curr_tx_buf_size; - u32 tx_tbl_num; - struct mwifiex_ds_tx_ba_stream_tbl - tx_tbl[MWIFIEX_MAX_TX_BASTREAM_SUPPORTED]; - u32 rx_tbl_num; - struct mwifiex_ds_rx_reorder_tbl rx_tbl - [MWIFIEX_MAX_RX_BASTREAM_SUPPORTED]; - u16 ps_mode; - u32 ps_state; - u8 is_deep_sleep; - u8 pm_wakeup_card_req; - u32 pm_wakeup_fw_try; - u8 is_hs_configured; - u8 hs_activated; - u32 num_cmd_host_to_card_failure; - u32 num_cmd_sleep_cfm_host_to_card_failure; - u32 num_tx_host_to_card_failure; - u32 num_event_deauth; - u32 num_event_disassoc; - u32 num_event_link_lost; - u32 num_cmd_deauth; - u32 num_cmd_assoc_success; - u32 num_cmd_assoc_failure; - u32 num_tx_timeout; - u32 num_cmd_timeout; - u16 timeout_cmd_id; - u16 timeout_cmd_act; - u16 last_cmd_id[DBG_CMD_NUM]; - u16 last_cmd_act[DBG_CMD_NUM]; - u16 last_cmd_index; - u16 last_cmd_resp_id[DBG_CMD_NUM]; - u16 last_cmd_resp_index; - u16 last_event[DBG_CMD_NUM]; - u16 last_event_index; - u8 data_sent; - u8 cmd_sent; - u8 cmd_resp_received; - u8 event_received; -}; - -#define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 -#define WAPI_RXPN_LEN 16 - -struct mwifiex_ds_encrypt_key { - u32 key_disable; - u32 key_index; - u32 key_len; - u8 key_material[WLAN_MAX_KEY_LEN]; - u8 mac_addr[ETH_ALEN]; - u32 is_wapi_key; - u8 wapi_rxpn[WAPI_RXPN_LEN]; -}; - -struct mwifiex_rate_cfg { - u32 action; - u32 is_rate_auto; - u32 rate; -}; - -struct mwifiex_data_rate { - u32 tx_data_rate; - u32 rx_data_rate; -}; - -struct mwifiex_power_cfg { - u32 is_power_auto; - u32 power_level; -}; - -struct mwifiex_ds_hs_cfg { - u32 is_invoke_hostcmd; - /* Bit0: non-unicast data - * Bit1: unicast data - * Bit2: mac events - * Bit3: magic packet - */ - u32 conditions; - u32 gpio; - u32 gap; -}; - -#define DEEP_SLEEP_ON 1 -#define DEEP_SLEEP_OFF 0 - -#define DEEP_SLEEP_IDLE_TIME 100 - -struct mwifiex_ds_auto_ds { - u16 auto_ds; - u16 idle_time; -}; - -#define PS_MODE_UNCHANGED 0 -#define PS_MODE_AUTO 1 -#define PS_MODE_POLL 2 -#define PS_MODE_NULL 3 - - -struct mwifiex_ds_pm_cfg { - union { - u32 ps_mode; - struct mwifiex_ds_hs_cfg hs_cfg; - struct mwifiex_ds_auto_ds auto_deep_sleep; - u32 sleep_period; - } param; -}; - -struct mwifiex_ioctl_wmm_queue_status_ac { - u8 wmm_acm; - u8 flow_required; - u8 flow_created; - u8 disabled; -}; - -struct mwifiex_ds_wmm_queue_status { - struct mwifiex_ioctl_wmm_queue_status_ac - ac_status[IEEE80211_MAX_QUEUES]; -}; - -struct mwifiex_ds_11n_tx_cfg { - u16 tx_htcap; - u16 tx_htinfo; -}; - -struct mwifiex_ds_11n_amsdu_aggr_ctrl { - u16 enable; - u16 curr_buf_size; -}; - -#define MWIFIEX_NUM_OF_CMD_BUFFER 20 -#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048 - -enum { - MWIFIEX_IE_TYPE_GEN_IE = 0, - MWIFIEX_IE_TYPE_ARP_FILTER, -}; - -enum { - MWIFIEX_REG_MAC = 1, - MWIFIEX_REG_BBP, - MWIFIEX_REG_RF, - MWIFIEX_REG_PMIC, - MWIFIEX_REG_CAU, -}; - -struct mwifiex_ds_reg_rw { - __le32 type; - __le32 offset; - __le32 value; -}; - -#define MAX_EEPROM_DATA 256 - -struct mwifiex_ds_read_eeprom { - __le16 offset; - __le16 byte_count; - u8 value[MAX_EEPROM_DATA]; -}; - -struct mwifiex_ds_misc_gen_ie { - u32 type; - u32 len; - u8 ie_data[IW_CUSTOM_MAX]; -}; - -struct mwifiex_ds_misc_cmd { - u32 len; - u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER]; -}; - -#define MWIFIEX_MAX_VSIE_LEN (256) -#define MWIFIEX_MAX_VSIE_NUM (8) -#define MWIFIEX_VSIE_MASK_SCAN 0x01 -#define MWIFIEX_VSIE_MASK_ASSOC 0x02 -#define MWIFIEX_VSIE_MASK_ADHOC 0x04 - -enum { - MWIFIEX_FUNC_INIT = 1, - MWIFIEX_FUNC_SHUTDOWN, -}; - -#endif /* !_MWIFIEX_IOCTL_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/join.c b/trunk/drivers/net/wireless/mwifiex/join.c deleted file mode 100644 index 042eb7701d04..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/join.c +++ /dev/null @@ -1,1419 +0,0 @@ -/* - * Marvell Wireless LAN device driver: association and ad-hoc start/join - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) - -/* - * Append a generic IE as a pass through TLV to a TLV buffer. - * - * This function is called from the network join command preparation routine. - * - * If the IE buffer has been setup by the application, this routine appends - * the buffer as a pass through TLV type to the request. - */ -static int -mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer) -{ - int ret_len = 0; - struct mwifiex_ie_types_header ie_header; - - /* Null Checks */ - if (!buffer) - return 0; - if (!(*buffer)) - return 0; - - /* - * If there is a generic ie buffer setup, append it to the return - * parameter buffer pointer. - */ - if (priv->gen_ie_buf_len) { - dev_dbg(priv->adapter->dev, "info: %s: append generic %d to %p\n", - __func__, priv->gen_ie_buf_len, *buffer); - - /* Wrap the generic IE buffer with a pass through TLV type */ - ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); - ie_header.len = cpu_to_le16(priv->gen_ie_buf_len); - memcpy(*buffer, &ie_header, sizeof(ie_header)); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += sizeof(ie_header); - ret_len += sizeof(ie_header); - - /* Copy the generic IE buffer to the output buffer, advance - pointer */ - memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += priv->gen_ie_buf_len; - ret_len += priv->gen_ie_buf_len; - - /* Reset the generic IE buffer */ - priv->gen_ie_buf_len = 0; - } - - /* return the length appended to the buffer */ - return ret_len; -} - -/* - * Append TSF tracking info from the scan table for the target AP. - * - * This function is called from the network join command preparation routine. - * - * The TSF table TSF sent to the firmware contains two TSF values: - * - The TSF of the target AP from its previous beacon/probe response - * - The TSF timestamp of our local MAC at the time we observed the - * beacon/probe response. - * - * The firmware uses the timestamp values to set an initial TSF value - * in the MAC for the new association after a reassociation attempt. - */ -static int -mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, - struct mwifiex_bssdescriptor *bss_desc) -{ - struct mwifiex_ie_types_tsf_timestamp tsf_tlv; - long long tsf_val; - - /* Null Checks */ - if (buffer == NULL) - return 0; - if (*buffer == NULL) - return 0; - - memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp)); - - tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); - tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val)); - - memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); - *buffer += sizeof(tsf_tlv.header); - - memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val)); - - dev_dbg(priv->adapter->dev, "info: %s: TSF offset calc: %016llx - " - "%016llx\n", __func__, tsf_val, bss_desc->network_tsf); - - memcpy(*buffer, &tsf_val, sizeof(tsf_val)); - *buffer += sizeof(tsf_val); - - return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); -} - -/* - * This function finds out the common rates between rate1 and rate2. - * - * It will fill common rates in rate1 as output if found. - * - * NOTE: Setting the MSB of the basic rates needs to be taken - * care of, either before or after calling this function. - */ -static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, - u32 rate1_size, u8 *rate2, u32 rate2_size) -{ - int ret = 0; - u8 *ptr = rate1; - u8 *tmp = NULL; - u32 i, j; - - tmp = kmalloc(rate1_size, GFP_KERNEL); - if (!tmp) { - dev_err(priv->adapter->dev, "failed to alloc tmp buf\n"); - return -ENOMEM; - } - - memcpy(tmp, rate1, rate1_size); - memset(rate1, 0, rate1_size); - - for (i = 0; rate2[i] && i < rate2_size; i++) { - for (j = 0; tmp[j] && j < rate1_size; j++) { - /* Check common rate, excluding the bit for - basic rate */ - if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { - *rate1++ = tmp[j]; - break; - } - } - } - - dev_dbg(priv->adapter->dev, "info: Tx data rate set to %#x\n", - priv->data_rate); - - if (!priv->is_data_rate_auto) { - while (*ptr) { - if ((*ptr & 0x7f) == priv->data_rate) { - ret = 0; - goto done; - } - ptr++; - } - dev_err(priv->adapter->dev, "previously set fixed data rate %#x" - " is not compatible with the network\n", - priv->data_rate); - - ret = -1; - goto done; - } - - ret = 0; -done: - kfree(tmp); - return ret; -} - -/* - * This function creates the intersection of the rates supported by a - * target BSS and our adapter settings for use in an assoc/join command. - */ -static int -mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 *out_rates, u32 *out_rates_size) -{ - u8 card_rates[MWIFIEX_SUPPORTED_RATES]; - u32 card_rates_size = 0; - - /* Copy AP supported rates */ - memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); - /* Get the STA supported rates */ - card_rates_size = mwifiex_get_active_data_rates(priv, card_rates); - /* Get the common rates between AP and STA supported rates */ - if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES, - card_rates, card_rates_size)) { - *out_rates_size = 0; - dev_err(priv->adapter->dev, "%s: cannot get common rates\n", - __func__); - return -1; - } - - *out_rates_size = - min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES); - - return 0; -} - -/* - * This function updates the scan entry TSF timestamps to reflect - * a new association. - */ -static void -mwifiex_update_tsf_timestamps(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *new_bss_desc) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u32 table_idx; - long long new_tsf_base; - signed long long tsf_delta; - - memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base)); - - tsf_delta = new_tsf_base - new_bss_desc->network_tsf; - - dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, " - "0x%016llx -> 0x%016llx\n", - new_bss_desc->network_tsf, new_tsf_base); - - for (table_idx = 0; table_idx < adapter->num_in_scan_table; - table_idx++) - adapter->scan_table[table_idx].network_tsf += tsf_delta; -} - -/* - * This function appends a WAPI IE. - * - * This function is called from the network join command preparation routine. - * - * If the IE buffer has been setup by the application, this routine appends - * the buffer as a WAPI TLV type to the request. - */ -static int -mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer) -{ - int retLen = 0; - struct mwifiex_ie_types_header ie_header; - - /* Null Checks */ - if (buffer == NULL) - return 0; - if (*buffer == NULL) - return 0; - - /* - * If there is a wapi ie buffer setup, append it to the return - * parameter buffer pointer. - */ - if (priv->wapi_ie_len) { - dev_dbg(priv->adapter->dev, "cmd: append wapi ie %d to %p\n", - priv->wapi_ie_len, *buffer); - - /* Wrap the generic IE buffer with a pass through TLV type */ - ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE); - ie_header.len = cpu_to_le16(priv->wapi_ie_len); - memcpy(*buffer, &ie_header, sizeof(ie_header)); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += sizeof(ie_header); - retLen += sizeof(ie_header); - - /* Copy the wapi IE buffer to the output buffer, advance - pointer */ - memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += priv->wapi_ie_len; - retLen += priv->wapi_ie_len; - - } - /* return the length appended to the buffer */ - return retLen; -} - -/* - * This function appends rsn ie tlv for wpa/wpa2 security modes. - * It is called from the network join command preparation routine. - */ -static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv, - u8 **buffer) -{ - struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv; - int rsn_ie_len; - - if (!buffer || !(*buffer)) - return 0; - - rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer); - rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]); - rsn_ie_tlv->header.type = cpu_to_le16( - le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); - rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]); - rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) - & 0x00FF); - if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2)) - memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], - le16_to_cpu(rsn_ie_tlv->header.len)); - else - return -1; - - rsn_ie_len = sizeof(rsn_ie_tlv->header) + - le16_to_cpu(rsn_ie_tlv->header.len); - *buffer += rsn_ie_len; - - return rsn_ie_len; -} - -/* - * This function prepares command for association. - * - * This sets the following parameters - - * - Peer MAC address - * - Listen interval - * - Beacon interval - * - Capability information - * - * ...and the following TLVs, as required - - * - SSID TLV - * - PHY TLV - * - SS TLV - * - Rates TLV - * - Authentication TLV - * - Channel TLV - * - WPA/WPA2 IE - * - 11n TLV - * - Vendor specific TLV - * - WMM TLV - * - WAPI IE - * - Generic IE - * - TSF TLV - * - * Preparation also includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) -{ - struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; - struct mwifiex_bssdescriptor *bss_desc; - struct mwifiex_ie_types_ssid_param_set *ssid_tlv; - struct mwifiex_ie_types_phy_param_set *phy_tlv; - struct mwifiex_ie_types_ss_param_set *ss_tlv; - struct mwifiex_ie_types_rates_param_set *rates_tlv; - struct mwifiex_ie_types_auth_type *auth_tlv; - struct mwifiex_ie_types_chan_list_param_set *chan_tlv; - u8 rates[MWIFIEX_SUPPORTED_RATES]; - u32 rates_size; - u16 tmp_cap; - u8 *pos; - int rsn_ie_len = 0; - - bss_desc = (struct mwifiex_bssdescriptor *) data_buf; - pos = (u8 *) assoc; - - mwifiex_cfg_tx_buf(priv, bss_desc); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); - - /* Save so we know which BSS Desc to use in the response handler */ - priv->attempted_bss_desc = bss_desc; - - memcpy(assoc->peer_sta_addr, - bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); - pos += sizeof(assoc->peer_sta_addr); - - /* Set the listen interval */ - assoc->listen_interval = cpu_to_le16(priv->listen_interval); - /* Set the beacon period */ - assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period); - - pos += sizeof(assoc->cap_info_bitmap); - pos += sizeof(assoc->listen_interval); - pos += sizeof(assoc->beacon_period); - pos += sizeof(assoc->dtim_period); - - ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos; - ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID); - ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len); - memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, - le16_to_cpu(ssid_tlv->header.len)); - pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); - - phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos; - phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS); - phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); - memcpy(&phy_tlv->fh_ds.ds_param_set, - &bss_desc->phy_param_set.ds_param_set.current_chan, - sizeof(phy_tlv->fh_ds.ds_param_set)); - pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); - - ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos; - ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS); - ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); - pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); - - /* Get the common rates supported between the driver and the BSS Desc */ - if (mwifiex_setup_rates_from_bssdesc - (priv, bss_desc, rates, &rates_size)) - return -1; - - /* Save the data rates into Current BSS state structure */ - priv->curr_bss_params.num_of_rates = rates_size; - memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); - - /* Setup the Rates TLV in the association command */ - rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos; - rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); - rates_tlv->header.len = cpu_to_le16((u16) rates_size); - memcpy(rates_tlv->rates, rates, rates_size); - pos += sizeof(rates_tlv->header) + rates_size; - dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n", - rates_size); - - /* Add the Authentication type to be used for Auth frames */ - auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; - auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); - auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) - auth_tlv->auth_type = cpu_to_le16( - (u16) priv->sec_info.authentication_mode); - else - auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); - - pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); - - if (IS_SUPPORT_MULTI_BANDS(priv->adapter) - && !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) - && (!bss_desc->disable_11n) - && (priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN) - && (bss_desc->bcn_ht_cap) - ) - ) { - /* Append a channel TLV for the channel the attempted AP was - found on */ - chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); - - memset(chan_tlv->chan_scan_param, 0x00, - sizeof(struct mwifiex_chan_scan_param_set)); - chan_tlv->chan_scan_param[0].chan_number = - (bss_desc->phy_param_set.ds_param_set.current_chan); - dev_dbg(priv->adapter->dev, "info: Assoc: TLV Chan = %d\n", - chan_tlv->chan_scan_param[0].chan_number); - - chan_tlv->chan_scan_param[0].radio_type = - mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - - dev_dbg(priv->adapter->dev, "info: Assoc: TLV Band = %d\n", - chan_tlv->chan_scan_param[0].radio_type); - pos += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - } - - if (!priv->wps.session_enable) { - if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) - rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); - - if (rsn_ie_len == -1) - return -1; - } - - if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) - && (!bss_desc->disable_11n) - && (priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN)) - mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); - - /* Append vendor specific IE TLV */ - mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); - - mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, - bss_desc->bcn_ht_cap); - if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) - mwifiex_cmd_append_wapi_ie(priv, &pos); - - - mwifiex_cmd_append_generic_ie(priv, &pos); - - mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); - - cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); - - /* Set the Capability info at last */ - tmp_cap = bss_desc->cap_info_bitmap; - - if (priv->adapter->config_bands == BAND_B) - tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; - - tmp_cap &= CAPINFO_MASK; - dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", - tmp_cap, CAPINFO_MASK); - assoc->cap_info_bitmap = cpu_to_le16(tmp_cap); - - return 0; -} - -/* - * Association firmware command response handler - * - * The response buffer for the association command has the following - * memory layout. - * - * For cases where an association response was not received (indicated - * by the CapInfo and AId field): - * - * .------------------------------------------------------------. - * | Header(4 * sizeof(t_u16)): Standard command response hdr | - * .------------------------------------------------------------. - * | cap_info/Error Return(t_u16): | - * | 0xFFFF(-1): Internal error | - * | 0xFFFE(-2): Authentication unhandled message | - * | 0xFFFD(-3): Authentication refused | - * | 0xFFFC(-4): Timeout waiting for AP response | - * .------------------------------------------------------------. - * | status_code(t_u16): | - * | If cap_info is -1: | - * | An internal firmware failure prevented the | - * | command from being processed. The status_code | - * | will be set to 1. | - * | | - * | If cap_info is -2: | - * | An authentication frame was received but was | - * | not handled by the firmware. IEEE Status | - * | code for the failure is returned. | - * | | - * | If cap_info is -3: | - * | An authentication frame was received and the | - * | status_code is the IEEE Status reported in the | - * | response. | - * | | - * | If cap_info is -4: | - * | (1) Association response timeout | - * | (2) Authentication response timeout | - * .------------------------------------------------------------. - * | a_id(t_u16): 0xFFFF | - * .------------------------------------------------------------. - * - * - * For cases where an association response was received, the IEEE - * standard association response frame is returned: - * - * .------------------------------------------------------------. - * | Header(4 * sizeof(t_u16)): Standard command response hdr | - * .------------------------------------------------------------. - * | cap_info(t_u16): IEEE Capability | - * .------------------------------------------------------------. - * | status_code(t_u16): IEEE Status Code | - * .------------------------------------------------------------. - * | a_id(t_u16): IEEE Association ID | - * .------------------------------------------------------------. - * | IEEE IEs(variable): Any received IEs comprising the | - * | remaining portion of a received | - * | association response frame. | - * .------------------------------------------------------------. - * - * For simplistic handling, the status_code field can be used to determine - * an association success (0) or failure (non-zero). - */ -int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - struct ieee_types_assoc_rsp *assoc_rsp; - struct mwifiex_bssdescriptor *bss_desc; - u8 enable_data = true; - - assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; - - priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, - sizeof(priv->assoc_rsp_buf)); - - memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); - - if (le16_to_cpu(assoc_rsp->status_code)) { - priv->adapter->dbg.num_cmd_assoc_failure++; - dev_err(priv->adapter->dev, "ASSOC_RESP: association failed, " - "status code = %d, error = 0x%x, a_id = 0x%x\n", - le16_to_cpu(assoc_rsp->status_code), - le16_to_cpu(assoc_rsp->cap_info_bitmap), - le16_to_cpu(assoc_rsp->a_id)); - - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->media_connected = true; - - priv->adapter->ps_state = PS_STATE_AWAKE; - priv->adapter->pps_uapsd_mode = false; - priv->adapter->tx_lock_flag = false; - - /* Set the attempted BSSID Index to current */ - bss_desc = priv->attempted_bss_desc; - - dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n", - bss_desc->ssid.ssid); - - /* Make a copy of current BSSID descriptor */ - memcpy(&priv->curr_bss_params.bss_descriptor, - bss_desc, sizeof(struct mwifiex_bssdescriptor)); - - /* Update curr_bss_params */ - priv->curr_bss_params.bss_descriptor.channel - = bss_desc->phy_param_set.ds_param_set.current_chan; - - priv->curr_bss_params.band = (u8) bss_desc->bss_band; - - /* - * Adjust the timestamps in the scan table to be relative to the newly - * associated AP's TSF - */ - mwifiex_update_tsf_timestamps(priv, bss_desc); - - if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) - priv->curr_bss_params.wmm_enabled = true; - else - priv->curr_bss_params.wmm_enabled = false; - - if ((priv->wmm_required || bss_desc->bcn_ht_cap) - && priv->curr_bss_params.wmm_enabled) - priv->wmm_enabled = true; - else - priv->wmm_enabled = false; - - priv->curr_bss_params.wmm_uapsd_enabled = false; - - if (priv->wmm_enabled) - priv->curr_bss_params.wmm_uapsd_enabled - = ((bss_desc->wmm_ie.qos_info_bitmap & - IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); - - dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", - priv->curr_pkt_filter); - if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) - priv->wpa_is_gtk_set = false; - - if (priv->wmm_enabled) { - /* Don't re-enable carrier until we get the WMM_GET_STATUS - event */ - enable_data = false; - } else { - /* Since WMM is not enabled, setup the queues with the - defaults */ - mwifiex_wmm_setup_queue_priorities(priv, NULL); - mwifiex_wmm_setup_ac_downgrade(priv); - } - - if (enable_data) - dev_dbg(priv->adapter->dev, - "info: post association, re-enabling data flow\n"); - - /* Reset SNR/NF/RSSI values */ - priv->data_rssi_last = 0; - priv->data_nf_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->bcn_rssi_last = 0; - priv->bcn_nf_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - priv->rxpd_rate = 0; - priv->rxpd_htinfo = 0; - - mwifiex_save_curr_bcn(priv); - - priv->adapter->dbg.num_cmd_assoc_success++; - - dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: associated\n"); - - /* Add the ra_list here for infra mode as there will be only 1 ra - always */ - mwifiex_ralist_add(priv, - priv->curr_bss_params.bss_descriptor.mac_address); - - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - if (netif_queue_stopped(priv->netdev)) - netif_wake_queue(priv->netdev); - - if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) - priv->scan_block = true; - -done: - /* Need to indicate IOCTL complete */ - if (adapter->curr_cmd->wait_q_enabled) { - if (ret) - adapter->cmd_wait_q.status = -1; - else - adapter->cmd_wait_q.status = 0; - } - - return ret; -} - -/* - * This function prepares command for ad-hoc start. - * - * Driver will fill up SSID, BSS mode, IBSS parameters, physical - * parameters, probe delay, and capability information. Firmware - * will fill up beacon period, basic rates and operational rates. - * - * In addition, the following TLVs are added - - * - Channel TLV - * - Vendor specific IE - * - WPA/WPA2 IE - * - HT Capabilities IE - * - HT Information IE - * - * Preparation also includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -int -mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) -{ - int rsn_ie_len = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start = - &cmd->params.adhoc_start; - struct mwifiex_bssdescriptor *bss_desc; - u32 cmd_append_size = 0; - u32 i; - u16 tmp_cap; - uint16_t ht_cap_info; - struct mwifiex_ie_types_chan_list_param_set *chan_tlv; - - struct mwifiex_ie_types_htcap *ht_cap; - struct mwifiex_ie_types_htinfo *ht_info; - u8 *pos = (u8 *) adhoc_start + - sizeof(struct host_cmd_ds_802_11_ad_hoc_start); - - if (!adapter) - return -1; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START); - - bss_desc = &priv->curr_bss_params.bss_descriptor; - priv->attempted_bss_desc = bss_desc; - - /* - * Fill in the parameters for 2 data structures: - * 1. struct host_cmd_ds_802_11_ad_hoc_start command - * 2. bss_desc - * Driver will fill up SSID, bss_mode,IBSS param, Physical Param, - * probe delay, and Cap info. - * Firmware will fill up beacon period, Basic rates - * and operational rates. - */ - - memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); - - memcpy(adhoc_start->ssid, - ((struct mwifiex_802_11_ssid *) data_buf)->ssid, - ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); - - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n", - adhoc_start->ssid); - - memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); - memcpy(bss_desc->ssid.ssid, - ((struct mwifiex_802_11_ssid *) data_buf)->ssid, - ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); - - bss_desc->ssid.ssid_len = - ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len; - - /* Set the BSS mode */ - adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; - bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; - adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); - bss_desc->beacon_period = priv->beacon_period; - - /* Set Physical param set */ -/* Parameter IE Id */ -#define DS_PARA_IE_ID 3 -/* Parameter IE length */ -#define DS_PARA_IE_LEN 1 - - adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID; - adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN; - - if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, adapter->adhoc_start_band, (u16) - priv->adhoc_channel)) { - struct mwifiex_chan_freq_power *cfp; - cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, - adapter->adhoc_start_band, FIRST_VALID_CHANNEL); - if (cfp) - priv->adhoc_channel = (u8) cfp->channel; - } - - if (!priv->adhoc_channel) { - dev_err(adapter->dev, "ADHOC_S_CMD: adhoc_channel cannot be 0\n"); - return -1; - } - - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: creating ADHOC on channel %d\n", - priv->adhoc_channel); - - priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel; - priv->curr_bss_params.band = adapter->adhoc_start_band; - - bss_desc->channel = priv->adhoc_channel; - adhoc_start->phy_param_set.ds_param_set.current_chan = - priv->adhoc_channel; - - memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set, - sizeof(union ieee_types_phy_param_set)); - - /* Set IBSS param set */ -/* IBSS parameter IE Id */ -#define IBSS_PARA_IE_ID 6 -/* IBSS parameter IE length */ -#define IBSS_PARA_IE_LEN 2 - - adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID; - adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN; - adhoc_start->ss_param_set.ibss_param_set.atim_window - = cpu_to_le16(priv->atim_window); - memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set, - sizeof(union ieee_types_ss_param_set)); - - /* Set Capability info */ - bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; - tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap); - tmp_cap &= ~WLAN_CAPABILITY_ESS; - tmp_cap |= WLAN_CAPABILITY_IBSS; - - /* Set up privacy in bss_desc */ - if (priv->sec_info.encryption_mode) { - /* Ad-Hoc capability privacy on */ - dev_dbg(adapter->dev, - "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; - tmp_cap |= WLAN_CAPABILITY_PRIVACY; - } else { - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status NOT set," - " setting privacy to ACCEPT ALL\n"); - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; - } - - memset(adhoc_start->DataRate, 0, sizeof(adhoc_start->DataRate)); - mwifiex_get_active_data_rates(priv, adhoc_start->DataRate); - if ((adapter->adhoc_start_band & BAND_G) && - (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { - if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter)) { - dev_err(adapter->dev, - "ADHOC_S_CMD: G Protection config failed\n"); - return -1; - } - } - /* Find the last non zero */ - for (i = 0; i < sizeof(adhoc_start->DataRate) && - adhoc_start->DataRate[i]; - i++) - ; - - priv->curr_bss_params.num_of_rates = i; - - /* Copy the ad-hoc creating rates into Current BSS rate structure */ - memcpy(&priv->curr_bss_params.data_rates, - &adhoc_start->DataRate, priv->curr_bss_params.num_of_rates); - - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%02x %02x %02x %02x\n", - adhoc_start->DataRate[0], adhoc_start->DataRate[1], - adhoc_start->DataRate[2], adhoc_start->DataRate[3]); - - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); - - if (IS_SUPPORT_MULTI_BANDS(adapter)) { - /* Append a channel TLV */ - chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); - - memset(chan_tlv->chan_scan_param, 0x00, - sizeof(struct mwifiex_chan_scan_param_set)); - chan_tlv->chan_scan_param[0].chan_number = - (u8) priv->curr_bss_params.bss_descriptor.channel; - - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n", - chan_tlv->chan_scan_param[0].chan_number); - - chan_tlv->chan_scan_param[0].radio_type - = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - if (adapter->adhoc_start_band & BAND_GN - || adapter->adhoc_start_band & BAND_AN) { - if (adapter->chan_offset == SEC_CHANNEL_ABOVE) - chan_tlv->chan_scan_param[0].radio_type |= - SECOND_CHANNEL_ABOVE; - else if (adapter->chan_offset == SEC_CHANNEL_BELOW) - chan_tlv->chan_scan_param[0].radio_type |= - SECOND_CHANNEL_BELOW; - } - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n", - chan_tlv->chan_scan_param[0].radio_type); - pos += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - cmd_append_size += - sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - } - - /* Append vendor specific IE TLV */ - cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, - MWIFIEX_VSIE_MASK_ADHOC, &pos); - - if (priv->sec_info.wpa_enabled) { - rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); - if (rsn_ie_len == -1) - return -1; - cmd_append_size += rsn_ie_len; - } - - if (adapter->adhoc_11n_enabled) { - { - ht_cap = (struct mwifiex_ie_types_htcap *) pos; - memset(ht_cap, 0, - sizeof(struct mwifiex_ie_types_htcap)); - ht_cap->header.type = - cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); - - ht_cap_info |= IEEE80211_HT_CAP_SGI_20; - if (adapter->chan_offset) { - ht_cap_info |= IEEE80211_HT_CAP_SGI_40; - ht_cap_info |= IEEE80211_HT_CAP_DSSSCCK40; - ht_cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); - } - - ht_cap->ht_cap.ampdu_params_info - = IEEE80211_HT_MAX_AMPDU_64K; - ht_cap->ht_cap.mcs.rx_mask[0] = 0xff; - pos += sizeof(struct mwifiex_ie_types_htcap); - cmd_append_size += - sizeof(struct mwifiex_ie_types_htcap); - } - { - ht_info = (struct mwifiex_ie_types_htinfo *) pos; - memset(ht_info, 0, - sizeof(struct mwifiex_ie_types_htinfo)); - ht_info->header.type = - cpu_to_le16(WLAN_EID_HT_INFORMATION); - ht_info->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_info)); - ht_info->ht_info.control_chan = - (u8) priv->curr_bss_params.bss_descriptor. - channel; - if (adapter->chan_offset) { - ht_info->ht_info.ht_param = - adapter->chan_offset; - ht_info->ht_info.ht_param |= - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; - } - ht_info->ht_info.operation_mode = - cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - ht_info->ht_info.basic_set[0] = 0xff; - pos += sizeof(struct mwifiex_ie_types_htinfo); - cmd_append_size += - sizeof(struct mwifiex_ie_types_htinfo); - } - } - - cmd->size = cpu_to_le16((u16) - (sizeof(struct host_cmd_ds_802_11_ad_hoc_start) - + S_DS_GEN + cmd_append_size)); - - if (adapter->adhoc_start_band == BAND_B) - tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; - else - tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - - adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); - - return 0; -} - -/* - * This function prepares command for ad-hoc join. - * - * Most of the parameters are set up by copying from the target BSS descriptor - * from the scan response. - * - * In addition, the following TLVs are added - - * - Channel TLV - * - Vendor specific IE - * - WPA/WPA2 IE - * - 11n IE - * - * Preparation also includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -int -mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) -{ - int rsn_ie_len = 0; - struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = - &cmd->params.adhoc_join; - struct mwifiex_bssdescriptor *bss_desc = - (struct mwifiex_bssdescriptor *) data_buf; - struct mwifiex_ie_types_chan_list_param_set *chan_tlv; - u32 cmd_append_size = 0; - u16 tmp_cap; - u32 i, rates_size = 0; - u16 curr_pkt_filter; - u8 *pos = - (u8 *) adhoc_join + - sizeof(struct host_cmd_ds_802_11_ad_hoc_join); - -/* Use G protection */ -#define USE_G_PROTECTION 0x02 - if (bss_desc->erp_flags & USE_G_PROTECTION) { - curr_pkt_filter = - priv-> - curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; - - if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &curr_pkt_filter)) { - dev_err(priv->adapter->dev, - "ADHOC_J_CMD: G Protection config failed\n"); - return -1; - } - } - - priv->attempted_bss_desc = bss_desc; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); - - adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; - - adhoc_join->bss_descriptor.beacon_period - = cpu_to_le16(bss_desc->beacon_period); - - memcpy(&adhoc_join->bss_descriptor.bssid, - &bss_desc->mac_address, ETH_ALEN); - - memcpy(&adhoc_join->bss_descriptor.ssid, - &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); - - memcpy(&adhoc_join->bss_descriptor.phy_param_set, - &bss_desc->phy_param_set, - sizeof(union ieee_types_phy_param_set)); - - memcpy(&adhoc_join->bss_descriptor.ss_param_set, - &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); - - tmp_cap = bss_desc->cap_info_bitmap; - - tmp_cap &= CAPINFO_MASK; - - dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: tmp_cap=%4X" - " CAPINFO_MASK=%4lX\n", tmp_cap, CAPINFO_MASK); - - /* Information on BSSID descriptor passed to FW */ - dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID = %pM, SSID = %s\n", - adhoc_join->bss_descriptor.bssid, - adhoc_join->bss_descriptor.ssid); - - for (i = 0; bss_desc->supported_rates[i] && - i < MWIFIEX_SUPPORTED_RATES; - i++) - ; - rates_size = i; - - /* Copy Data Rates from the Rates recorded in scan response */ - memset(adhoc_join->bss_descriptor.data_rates, 0, - sizeof(adhoc_join->bss_descriptor.data_rates)); - memcpy(adhoc_join->bss_descriptor.data_rates, - bss_desc->supported_rates, rates_size); - - /* Copy the adhoc join rates into Current BSS state structure */ - priv->curr_bss_params.num_of_rates = rates_size; - memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, - rates_size); - - /* Copy the channel information */ - priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; - priv->curr_bss_params.band = (u8) bss_desc->bss_band; - - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED - || priv->sec_info.wpa_enabled) - tmp_cap |= WLAN_CAPABILITY_PRIVACY; - - if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { - /* Append a channel TLV */ - chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); - - memset(chan_tlv->chan_scan_param, 0x00, - sizeof(struct mwifiex_chan_scan_param_set)); - chan_tlv->chan_scan_param[0].chan_number = - (bss_desc->phy_param_set.ds_param_set.current_chan); - dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan = %d\n", - chan_tlv->chan_scan_param[0].chan_number); - - chan_tlv->chan_scan_param[0].radio_type = - mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - - dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band = %d\n", - chan_tlv->chan_scan_param[0].radio_type); - pos += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - cmd_append_size += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - } - - if (priv->sec_info.wpa_enabled) - rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); - if (rsn_ie_len == -1) - return -1; - cmd_append_size += rsn_ie_len; - - if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) - cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, - bss_desc, &pos); - - /* Append vendor specific IE TLV */ - cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, - MWIFIEX_VSIE_MASK_ADHOC, &pos); - - cmd->size = cpu_to_le16((u16) - (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) - + S_DS_GEN + cmd_append_size)); - - adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); - - return 0; -} - -/* - * This function handles the command response of ad-hoc start and - * ad-hoc join. - * - * The function generates a device-connected event to notify - * the applications, in case of successful ad-hoc start/join, and - * saves the beacon buffer. - */ -int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; - struct mwifiex_bssdescriptor *bss_desc; - - adhoc_result = &resp->params.adhoc_result; - - bss_desc = priv->attempted_bss_desc; - - /* Join result code 0 --> SUCCESS */ - if (le16_to_cpu(resp->result)) { - dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n"); - if (priv->media_connected) - mwifiex_reset_connect_state(priv); - - memset(&priv->curr_bss_params.bss_descriptor, - 0x00, sizeof(struct mwifiex_bssdescriptor)); - - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->media_connected = true; - - if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) { - dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n", - bss_desc->ssid.ssid); - - /* Update the created network descriptor with the new BSSID */ - memcpy(bss_desc->mac_address, - adhoc_result->bssid, ETH_ALEN); - - priv->adhoc_state = ADHOC_STARTED; - } else { - /* - * Now the join cmd should be successful. - * If BSSID has changed use SSID to compare instead of BSSID - */ - dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n", - bss_desc->ssid.ssid); - - /* - * Make a copy of current BSSID descriptor, only needed for - * join since the current descriptor is already being used - * for adhoc start - */ - memcpy(&priv->curr_bss_params.bss_descriptor, - bss_desc, sizeof(struct mwifiex_bssdescriptor)); - - priv->adhoc_state = ADHOC_JOINED; - } - - dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n", - priv->adhoc_channel); - dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n", - priv->curr_bss_params.bss_descriptor.mac_address); - - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - if (netif_queue_stopped(priv->netdev)) - netif_wake_queue(priv->netdev); - - mwifiex_save_curr_bcn(priv); - -done: - /* Need to indicate IOCTL complete */ - if (adapter->curr_cmd->wait_q_enabled) { - if (ret) - adapter->cmd_wait_q.status = -1; - else - adapter->cmd_wait_q.status = 0; - - } - - return ret; -} - -/* - * This function associates to a specific BSS discovered in a scan. - * - * It clears any past association response stored for application - * retrieval and calls the command preparation routine to send the - * command to firmware. - */ -int mwifiex_associate(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - u8 current_bssid[ETH_ALEN]; - - /* Return error if the adapter or table entry is not marked as infra */ - if ((priv->bss_mode != NL80211_IFTYPE_STATION) || - (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) - return -1; - - memcpy(¤t_bssid, - &priv->curr_bss_params.bss_descriptor.mac_address, - sizeof(current_bssid)); - - /* Clear any past association response stored for application - retrieval */ - priv->assoc_rsp_size = 0; - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, - HostCmd_ACT_GEN_SET, 0, bss_desc); -} - -/* - * This function starts an ad-hoc network. - * - * It calls the command preparation routine to send the command to firmware. - */ -int -mwifiex_adhoc_start(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *adhoc_ssid) -{ - dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n", - priv->adhoc_channel); - dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", - priv->curr_bss_params.bss_descriptor.channel); - dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", - priv->curr_bss_params.band); - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, - HostCmd_ACT_GEN_SET, 0, adhoc_ssid); -} - -/* - * This function joins an ad-hoc network found in a previous scan. - * - * It calls the command preparation routine to send the command to firmware, - * if already not connected to the requested SSID. - */ -int mwifiex_adhoc_join(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n", - priv->curr_bss_params.bss_descriptor.ssid.ssid); - dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n", - priv->curr_bss_params.bss_descriptor.ssid.ssid_len); - dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n", - bss_desc->ssid.ssid); - dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n", - bss_desc->ssid.ssid_len); - - /* Check if the requested SSID is already joined */ - if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && - !mwifiex_ssid_cmp(&bss_desc->ssid, - &priv->curr_bss_params.bss_descriptor.ssid) && - (priv->curr_bss_params.bss_descriptor.bss_mode == - NL80211_IFTYPE_ADHOC)) { - dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID" - " is the same as current; not attempting to re-join\n"); - return -1; - } - - dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", - priv->curr_bss_params.bss_descriptor.channel); - dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", - priv->curr_bss_params.band); - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, - HostCmd_ACT_GEN_SET, 0, bss_desc); -} - -/* - * This function deauthenticates/disconnects from infra network by sending - * deauthentication request. - */ -static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) -{ - u8 mac_address[ETH_ALEN]; - int ret = 0; - u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - - if (mac) { - if (!memcmp(mac, zero_mac, sizeof(zero_mac))) - memcpy((u8 *) &mac_address, - (u8 *) &priv->curr_bss_params.bss_descriptor. - mac_address, ETH_ALEN); - else - memcpy((u8 *) &mac_address, (u8 *) mac, ETH_ALEN); - } else { - memcpy((u8 *) &mac_address, (u8 *) &priv->curr_bss_params. - bss_descriptor.mac_address, ETH_ALEN); - } - - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, - HostCmd_ACT_GEN_SET, 0, &mac_address); - - return ret; -} - -/* - * This function deauthenticates/disconnects from a BSS. - * - * In case of infra made, it sends deauthentication request, and - * in case of ad-hoc mode, a stop network request is sent to the firmware. - */ -int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) -{ - int ret = 0; - - if (priv->media_connected) { - if (priv->bss_mode == NL80211_IFTYPE_STATION) { - ret = mwifiex_deauthenticate_infra(priv, mac); - } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - ret = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_AD_HOC_STOP, - HostCmd_ACT_GEN_SET, 0, NULL); - } - } - - return ret; -} -EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); - -/* - * This function converts band to radio type used in channel TLV. - */ -u8 -mwifiex_band_to_radio_type(u8 band) -{ - switch (band) { - case BAND_A: - case BAND_AN: - case BAND_A | BAND_AN: - return HostCmd_SCAN_RADIO_TYPE_A; - case BAND_B: - case BAND_G: - case BAND_B | BAND_G: - default: - return HostCmd_SCAN_RADIO_TYPE_BG; - } -} diff --git a/trunk/drivers/net/wireless/mwifiex/main.c b/trunk/drivers/net/wireless/mwifiex/main.c deleted file mode 100644 index c5971880e7b3..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/main.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * Marvell Wireless LAN device driver: major functions - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" -#include "wmm.h" -#include "cfg80211.h" -#include "11n.h" - -#define VERSION "1.0" - -const char driver_version[] = "mwifiex " VERSION " (%s) "; - -struct mwifiex_adapter *g_adapter; -EXPORT_SYMBOL_GPL(g_adapter); - -static struct mwifiex_bss_attr mwifiex_bss_sta[] = { - {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0}, -}; - -static int drv_mode = DRV_MODE_STA; - -static char fw_name[32] = DEFAULT_FW_NAME; - -/* Supported drv_mode table */ -static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { - { - .drv_mode = DRV_MODE_STA, - .intf_num = ARRAY_SIZE(mwifiex_bss_sta), - .bss_attr = mwifiex_bss_sta, - }, -}; - -/* - * This function registers the device and performs all the necessary - * initializations. - * - * The following initialization operations are performed - - * - Allocate adapter structure - * - Save interface specific operations table in adapter - * - Call interface specific initialization routine - * - Allocate private structures - * - Set default adapter structure parameters - * - Initialize locks - * - * In case of any errors during inittialization, this function also ensures - * proper cleanup before exiting. - */ -static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, - struct mwifiex_drv_mode *drv_mode_ptr) -{ - struct mwifiex_adapter *adapter; - int i; - - adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); - if (!adapter) - return -1; - - g_adapter = adapter; - adapter->card = card; - - /* Save interface specific operations in adapter */ - memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops)); - - /* card specific initialization has been deferred until now .. */ - if (adapter->if_ops.init_if(adapter)) - goto error; - - adapter->priv_num = 0; - for (i = 0; i < drv_mode_ptr->intf_num; i++) { - adapter->priv[i] = NULL; - - if (!drv_mode_ptr->bss_attr[i].active) - continue; - - /* Allocate memory for private structure */ - adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), - GFP_KERNEL); - if (!adapter->priv[i]) { - dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n", - __func__, i); - goto error; - } - - adapter->priv_num++; - adapter->priv[i]->adapter = adapter; - /* Save bss_type, frame_type & bss_priority */ - adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type; - adapter->priv[i]->frame_type = - drv_mode_ptr->bss_attr[i].frame_type; - adapter->priv[i]->bss_priority = - drv_mode_ptr->bss_attr[i].bss_priority; - - if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) - adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; - else if (drv_mode_ptr->bss_attr[i].bss_type == - MWIFIEX_BSS_TYPE_UAP) - adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP; - - /* Save bss_index & bss_num */ - adapter->priv[i]->bss_index = i; - adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num; - } - adapter->drv_mode = drv_mode_ptr; - - if (mwifiex_init_lock_list(adapter)) - goto error; - - init_timer(&adapter->cmd_timer); - adapter->cmd_timer.function = mwifiex_cmd_timeout_func; - adapter->cmd_timer.data = (unsigned long) adapter; - - return 0; - -error: - dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); - - mwifiex_free_lock_list(adapter); - for (i = 0; i < drv_mode_ptr->intf_num; i++) - kfree(adapter->priv[i]); - kfree(adapter); - - return -1; -} - -/* - * This function unregisters the device and performs all the necessary - * cleanups. - * - * The following cleanup operations are performed - - * - Free the timers - * - Free beacon buffers - * - Free private structures - * - Free adapter structure - */ -static int mwifiex_unregister(struct mwifiex_adapter *adapter) -{ - s32 i = 0; - - del_timer(&adapter->cmd_timer); - - /* Free private structures */ - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - mwifiex_free_curr_bcn(adapter->priv[i]); - kfree(adapter->priv[i]); - } - } - - kfree(adapter); - return 0; -} - -/* - * The main process. - * - * This function is the main procedure of the driver and handles various driver - * operations. It runs in a loop and provides the core functionalities. - * - * The main responsibilities of this function are - - * - Ensure concurrency control - * - Handle pending interrupts and call interrupt handlers - * - Wake up the card if required - * - Handle command responses and call response handlers - * - Handle events and call event handlers - * - Execute pending commands - * - Transmit pending data packets - */ -int mwifiex_main_process(struct mwifiex_adapter *adapter) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - - /* Check if already processing */ - if (adapter->mwifiex_processing) { - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - goto exit_main_proc; - } else { - adapter->mwifiex_processing = true; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - } -process_start: - do { - if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) || - (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)) - break; - - /* Handle pending interrupt if any */ - if (adapter->int_status) { - if (adapter->hs_activated) - mwifiex_process_hs_config(adapter); - adapter->if_ops.process_int_status(adapter); - } - - /* Need to wake up the card ? */ - if ((adapter->ps_state == PS_STATE_SLEEP) && - (adapter->pm_wakeup_card_req && - !adapter->pm_wakeup_fw_try) && - (is_command_pending(adapter) - || !mwifiex_wmm_lists_empty(adapter))) { - adapter->pm_wakeup_fw_try = true; - adapter->if_ops.wakeup(adapter); - continue; - } - if (IS_CARD_RX_RCVD(adapter)) { - adapter->pm_wakeup_fw_try = false; - if (adapter->ps_state == PS_STATE_SLEEP) - adapter->ps_state = PS_STATE_AWAKE; - } else { - /* We have tried to wakeup the card already */ - if (adapter->pm_wakeup_fw_try) - break; - if (adapter->ps_state != PS_STATE_AWAKE || - adapter->tx_lock_flag) - break; - - if (adapter->scan_processing || adapter->data_sent - || mwifiex_wmm_lists_empty(adapter)) { - if (adapter->cmd_sent || adapter->curr_cmd - || (!is_command_pending(adapter))) - break; - } - } - - /* Check for Cmd Resp */ - if (adapter->cmd_resp_received) { - adapter->cmd_resp_received = false; - mwifiex_process_cmdresp(adapter); - - /* call mwifiex back when init_fw is done */ - if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) { - adapter->hw_status = MWIFIEX_HW_STATUS_READY; - mwifiex_init_fw_complete(adapter); - } - } - - /* Check for event */ - if (adapter->event_received) { - adapter->event_received = false; - mwifiex_process_event(adapter); - } - - /* Check if we need to confirm Sleep Request - received previously */ - if (adapter->ps_state == PS_STATE_PRE_SLEEP) { - if (!adapter->cmd_sent && !adapter->curr_cmd) - mwifiex_check_ps_cond(adapter); - } - - /* * The ps_state may have been changed during processing of - * Sleep Request event. - */ - if ((adapter->ps_state == PS_STATE_SLEEP) - || (adapter->ps_state == PS_STATE_PRE_SLEEP) - || (adapter->ps_state == PS_STATE_SLEEP_CFM) - || adapter->tx_lock_flag) - continue; - - if (!adapter->cmd_sent && !adapter->curr_cmd) { - if (mwifiex_exec_next_cmd(adapter) == -1) { - ret = -1; - break; - } - } - - if (!adapter->scan_processing && !adapter->data_sent && - !mwifiex_wmm_lists_empty(adapter)) { - mwifiex_wmm_process_tx(adapter); - if (adapter->hs_activated) { - adapter->is_hs_configured = false; - mwifiex_hs_activated_event - (mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), - false); - } - } - - if (adapter->delay_null_pkt && !adapter->cmd_sent && - !adapter->curr_cmd && !is_command_pending(adapter) - && mwifiex_wmm_lists_empty(adapter)) { - if (!mwifiex_send_null_packet - (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) { - adapter->delay_null_pkt = false; - adapter->ps_state = PS_STATE_SLEEP; - } - break; - } - } while (true); - - if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) - goto process_start; - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - adapter->mwifiex_processing = false; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - -exit_main_proc: - if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) - mwifiex_shutdown_drv(adapter); - return ret; -} - -/* - * This function initializes the software. - * - * The main work includes allocating and initializing the adapter structure - * and initializing the private structures. - */ -static int -mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops) -{ - int i; - struct mwifiex_drv_mode *drv_mode_ptr; - - /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ - drv_mode_ptr = NULL; - for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) { - if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) { - drv_mode_ptr = &mwifiex_drv_mode_tbl[i]; - break; - } - } - - if (!drv_mode_ptr) { - pr_err("invalid drv_mode=%d\n", drv_mode); - return -1; - } - - if (mwifiex_register(card, if_ops, drv_mode_ptr)) - return -1; - - return 0; -} - -/* - * This function frees the adapter structure. - * - * Additionally, this closes the netlink socket, frees the timers - * and private structures. - */ -static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) -{ - if (!adapter) { - pr_err("%s: adapter is NULL\n", __func__); - return; - } - - mwifiex_unregister(adapter); - pr_debug("info: %s: free adapter\n", __func__); -} - -/* - * This function initializes the hardware and firmware. - * - * The main initialization steps followed are - - * - Download the correct firmware to card - * - Allocate and initialize the adapter structure - * - Initialize the private structures - * - Issue the init commands to firmware - */ -static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) -{ - int ret = 0; - int err; - struct mwifiex_fw_image fw; - - memset(&fw, 0, sizeof(struct mwifiex_fw_image)); - - switch (adapter->revision_id) { - case SD8787_W0: - case SD8787_W1: - strcpy(fw_name, SD8787_W1_FW_NAME); - break; - case SD8787_A0: - case SD8787_A1: - strcpy(fw_name, SD8787_AX_FW_NAME); - break; - default: - break; - } - - err = request_firmware(&adapter->firmware, fw_name, adapter->dev); - if (err < 0) { - dev_err(adapter->dev, "request_firmware() returned" - " error code %#x\n", err); - ret = -1; - goto done; - } - fw.fw_buf = (u8 *) adapter->firmware->data; - fw.fw_len = adapter->firmware->size; - - ret = mwifiex_dnld_fw(adapter, &fw); - if (ret == -1) - goto done; - - dev_notice(adapter->dev, "WLAN FW is active\n"); - - adapter->init_wait_q_woken = false; - ret = mwifiex_init_fw(adapter); - if (ret == -1) { - goto done; - } else if (!ret) { - adapter->hw_status = MWIFIEX_HW_STATUS_READY; - goto done; - } - /* Wait for mwifiex_init to complete */ - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) { - ret = -1; - goto done; - } - ret = 0; - -done: - if (adapter->firmware) - release_firmware(adapter->firmware); - if (ret) - ret = -1; - return ret; -} - -/* - * This function fills a driver buffer. - * - * The function associates a given SKB with the provided driver buffer - * and also updates some of the SKB parameters, including IP header, - * priority and timestamp. - */ -static void -mwifiex_fill_buffer(struct sk_buff *skb) -{ - struct ethhdr *eth = NULL; - struct iphdr *iph; - struct timeval tv; - u8 tid = 0; - - eth = (struct ethhdr *) skb->data; - switch (eth->h_proto) { - case __constant_htons(ETH_P_IP): - iph = ip_hdr(skb); - tid = IPTOS_PREC(iph->tos); - pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n", - eth->h_proto, tid, skb->priority); - break; - case __constant_htons(ETH_P_ARP): - pr_debug("data: ARP packet: %04x\n", eth->h_proto); - default: - break; - } -/* Offset for TOS field in the IP header */ -#define IPTOS_OFFSET 5 - tid = (tid >> IPTOS_OFFSET); - skb->priority = tid; - /* Record the current time the packet was queued; used to - determine the amount of time the packet was queued in - the driver before it was sent to the firmware. - The delay is then sent along with the packet to the - firmware for aggregate delay calculation for stats and - MSDU lifetime expiry. - */ - do_gettimeofday(&tv); - skb->tstamp = timeval_to_ktime(tv); -} - -/* - * CFG802.11 network device handler for open. - * - * Starts the data queue. - */ -static int -mwifiex_open(struct net_device *dev) -{ - netif_start_queue(dev); - return 0; -} - -/* - * CFG802.11 network device handler for close. - */ -static int -mwifiex_close(struct net_device *dev) -{ - return 0; -} - -/* - * CFG802.11 network device handler for data transmission. - */ -static int -mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct sk_buff *new_skb = NULL; - struct mwifiex_txinfo *tx_info; - - dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n", - jiffies, priv->bss_index); - - if (priv->adapter->surprise_removed) { - kfree(skb); - priv->stats.tx_dropped++; - return 0; - } - if (!skb->len || (skb->len > ETH_FRAME_LEN)) { - dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); - kfree(skb); - priv->stats.tx_dropped++; - return 0; - } - if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { - dev_dbg(priv->adapter->dev, - "data: Tx: insufficient skb headroom %d\n", - skb_headroom(skb)); - /* Insufficient skb headroom - allocate a new skb */ - new_skb = - skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); - if (unlikely(!new_skb)) { - dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); - kfree(skb); - priv->stats.tx_dropped++; - return 0; - } - kfree_skb(skb); - skb = new_skb; - dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n", - skb_headroom(skb)); - } - - tx_info = MWIFIEX_SKB_TXCB(skb); - tx_info->bss_index = priv->bss_index; - mwifiex_fill_buffer(skb); - - mwifiex_wmm_add_buf_txqueue(priv->adapter, skb); - atomic_inc(&priv->adapter->tx_pending); - - if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { - netif_stop_queue(priv->netdev); - dev->trans_start = jiffies; - } - - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); - - return 0; -} - -/* - * CFG802.11 network device handler for setting MAC address. - */ -static int -mwifiex_set_mac_address(struct net_device *dev, void *addr) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct sockaddr *hw_addr = (struct sockaddr *) addr; - int ret = 0; - - memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); - - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS, - HostCmd_ACT_GEN_SET, 0, NULL); - - if (!ret) - memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); - else - dev_err(priv->adapter->dev, "set mac address failed: ret=%d" - "\n", ret); - - memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); - - return ret; -} - -/* - * CFG802.11 network device handler for setting multicast list. - */ -static void mwifiex_set_multicast_list(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_multicast_list mcast_list; - - if (dev->flags & IFF_PROMISC) { - mcast_list.mode = MWIFIEX_PROMISC_MODE; - } else if (dev->flags & IFF_ALLMULTI || - netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { - mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; - } else { - mcast_list.mode = MWIFIEX_MULTICAST_MODE; - if (netdev_mc_count(dev)) - mcast_list.num_multicast_addr = - mwifiex_copy_mcast_addr(&mcast_list, dev); - } - mwifiex_request_set_multicast_list(priv, &mcast_list); -} - -/* - * CFG802.11 network device handler for transmission timeout. - */ -static void -mwifiex_tx_timeout(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n", - jiffies, priv->bss_index); - dev->trans_start = jiffies; - priv->num_tx_timeout++; -} - -/* - * CFG802.11 network device handler for statistics retrieval. - */ -static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - return &priv->stats; -} - -/* Network device handlers */ -static const struct net_device_ops mwifiex_netdev_ops = { - .ndo_open = mwifiex_open, - .ndo_stop = mwifiex_close, - .ndo_start_xmit = mwifiex_hard_start_xmit, - .ndo_set_mac_address = mwifiex_set_mac_address, - .ndo_tx_timeout = mwifiex_tx_timeout, - .ndo_get_stats = mwifiex_get_stats, - .ndo_set_multicast_list = mwifiex_set_multicast_list, -}; - -/* - * This function initializes the private structure parameters. - * - * The following wait queues are initialized - - * - IOCTL wait queue - * - Command wait queue - * - Statistics wait queue - * - * ...and the following default parameters are set - - * - Current key index : Set to 0 - * - Rate index : Set to auto - * - Media connected : Set to disconnected - * - Adhoc link sensed : Set to false - * - Nick name : Set to null - * - Number of Tx timeout : Set to 0 - * - Device address : Set to current address - * - * In addition, the CFG80211 work queue is also created. - */ -static void -mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) -{ - dev->netdev_ops = &mwifiex_netdev_ops; - /* Initialize private structure */ - priv->current_key_index = 0; - priv->media_connected = false; - memset(&priv->nick_name, 0, sizeof(priv->nick_name)); - priv->num_tx_timeout = 0; - priv->workqueue = create_singlethread_workqueue("cfg80211_wq"); - INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results); - memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); -} - -/* - * This function adds a new logical interface. - * - * It allocates, initializes and registers the interface by performing - * the following opearations - - * - Allocate a new net device structure - * - Assign device name - * - Register the new device with CFG80211 subsystem - * - Initialize semaphore and private structure - * - Register the new device with kernel - * - Create the complete debug FS structure if configured - */ -static struct mwifiex_private *mwifiex_add_interface( - struct mwifiex_adapter *adapter, - u8 bss_index, u8 bss_type) -{ - struct net_device *dev = NULL; - struct mwifiex_private *priv = NULL; - void *mdev_priv = NULL; - - dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", - ether_setup, 1); - if (!dev) { - dev_err(adapter->dev, "no memory available for netdevice\n"); - goto error; - } - if (dev_alloc_name(dev, dev->name)) { - dev_err(adapter->dev, "unable to alloc name for netdevice\n"); - goto error; - } - - if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, - adapter->priv[bss_index]) != 0) { - dev_err(adapter->dev, "cannot register netdevice with cfg80211\n"); - goto error; - } - /* Save the priv pointer in netdev */ - priv = adapter->priv[bss_index]; - mdev_priv = netdev_priv(dev); - *((unsigned long *) mdev_priv) = (unsigned long) priv; - - priv->netdev = dev; - - sema_init(&priv->async_sem, 1); - priv->scan_pending_on_block = false; - - mwifiex_init_priv_params(priv, dev); - - SET_NETDEV_DEV(dev, adapter->dev); - - /* Register network device */ - if (register_netdev(dev)) { - dev_err(adapter->dev, "cannot register virtual network device\n"); - goto error; - } - - dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_init(priv); -#endif - return priv; -error: - if (dev) - free_netdev(dev); - return NULL; -} - -/* - * This function removes a logical interface. - * - * It deregisters, resets and frees the interface by performing - * the following operations - - * - Disconnect the device if connected, send wireless event to - * notify applications. - * - Remove the debug FS structure if configured - * - Unregister the device from kernel - * - Free the net device structure - * - Cancel all works and destroy work queue - * - Unregister and free the wireless device from CFG80211 subsystem - */ -static void -mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) -{ - struct net_device *dev = NULL; - struct mwifiex_private *priv = adapter->priv[bss_index]; - - if (!priv) - return; - dev = priv->netdev; - - if (priv->media_connected) - priv->media_connected = false; - -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_remove(priv); -#endif - /* Last reference is our one */ - dev_dbg(adapter->dev, "info: %s: refcnt = %d\n", - dev->name, netdev_refcnt_read(dev)); - - if (dev->reg_state == NETREG_REGISTERED) - unregister_netdev(dev); - - /* Clear the priv in adapter */ - priv->netdev = NULL; - if (dev) - free_netdev(dev); - - cancel_work_sync(&priv->cfg_workqueue); - flush_workqueue(priv->workqueue); - destroy_workqueue(priv->workqueue); - wiphy_unregister(priv->wdev->wiphy); - wiphy_free(priv->wdev->wiphy); - kfree(priv->wdev); -} - -/* - * This function check if command is pending. - */ -int is_command_pending(struct mwifiex_adapter *adapter) -{ - unsigned long flags; - int is_cmd_pend_q_empty; - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - return !is_cmd_pend_q_empty; -} - -/* - * This function returns the correct private structure pointer based - * upon the BSS number. - */ -struct mwifiex_private * -mwifiex_bss_index_to_priv(struct mwifiex_adapter *adapter, u8 bss_index) -{ - if (!adapter || (bss_index >= adapter->priv_num)) - return NULL; - return adapter->priv[bss_index]; -} - -/* - * This is the main work queue function. - * - * It handles the main process, which in turn handles the complete - * driver operations. - */ -static void mwifiex_main_work_queue(struct work_struct *work) -{ - struct mwifiex_adapter *adapter = - container_of(work, struct mwifiex_adapter, main_work); - - if (adapter->surprise_removed) - return; - mwifiex_main_process(adapter); -} - -/* - * This function cancels all works in the queue and destroys - * the main workqueue. - */ -static void -mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) -{ - flush_workqueue(adapter->workqueue); - destroy_workqueue(adapter->workqueue); - adapter->workqueue = NULL; -} - -/* - * This function adds the card. - * - * This function follows the following major steps to set up the device - - * - Initialize software. This includes probing the card, registering - * the interface operations table, and allocating/initializing the - * adapter structure - * - Set up the netlink socket - * - Create and start the main work queue - * - Register the device - * - Initialize firmware and hardware - * - Add logical interfaces - */ -int -mwifiex_add_card(void *card, struct semaphore *sem, - struct mwifiex_if_ops *if_ops) -{ - int i; - struct mwifiex_adapter *adapter; - - if (down_interruptible(sem)) - goto exit_sem_err; - - if (mwifiex_init_sw(card, if_ops)) { - pr_err("%s: software init failed\n", __func__); - goto err_init_sw; - } - - adapter = g_adapter; - - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - adapter->surprise_removed = false; - init_waitqueue_head(&adapter->init_wait_q); - adapter->is_suspended = false; - adapter->hs_activated = false; - init_waitqueue_head(&adapter->hs_activate_wait_q); - adapter->cmd_wait_q_required = false; - init_waitqueue_head(&adapter->cmd_wait_q.wait); - adapter->cmd_wait_q.condition = false; - adapter->cmd_wait_q.status = 0; - - adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); - if (!adapter->workqueue) - goto err_kmalloc; - - INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); - - /* Register the device. Fill up the private data structure with relevant - information from the card and request for the required IRQ. */ - if (adapter->if_ops.register_dev(adapter)) { - pr_err("%s: failed to register mwifiex device\n", __func__); - goto err_registerdev; - } - - if (mwifiex_init_hw_fw(adapter)) { - pr_err("%s: firmware init failed\n", __func__); - goto err_init_fw; - } - - /* Add interfaces */ - for (i = 0; i < adapter->drv_mode->intf_num; i++) { - if (!mwifiex_add_interface(adapter, i, - adapter->drv_mode->bss_attr[i].bss_type)) { - goto err_add_intf; - } - } - - up(sem); - - return 0; - -err_add_intf: - for (i = 0; i < adapter->priv_num; i++) - mwifiex_remove_interface(adapter, i); -err_init_fw: - pr_debug("info: %s: unregister device\n", __func__); - adapter->if_ops.unregister_dev(adapter); -err_registerdev: - adapter->surprise_removed = true; - mwifiex_terminate_workqueue(adapter); -err_kmalloc: - if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) || - (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) { - pr_debug("info: %s: shutdown mwifiex\n", __func__); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - } - - mwifiex_free_adapter(adapter); - -err_init_sw: - up(sem); - -exit_sem_err: - return -1; -} -EXPORT_SYMBOL_GPL(mwifiex_add_card); - -/* - * This function removes the card. - * - * This function follows the following major steps to remove the device - - * - Stop data traffic - * - Shutdown firmware - * - Remove the logical interfaces - * - Terminate the work queue - * - Unregister the device - * - Free the adapter structure - */ -int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) -{ - struct mwifiex_private *priv = NULL; - int i; - - if (down_interruptible(sem)) - goto exit_sem_err; - - if (!adapter) - goto exit_remove; - - adapter->surprise_removed = true; - - /* Stop data */ - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) { - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - } - } - - dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n"); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n"); - if (atomic_read(&adapter->rx_pending) || - atomic_read(&adapter->tx_pending) || - atomic_read(&adapter->cmd_pending)) { - dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " - "cmd_pending=%d\n", - atomic_read(&adapter->rx_pending), - atomic_read(&adapter->tx_pending), - atomic_read(&adapter->cmd_pending)); - } - - /* Remove interface */ - for (i = 0; i < adapter->priv_num; i++) - mwifiex_remove_interface(adapter, i); - - mwifiex_terminate_workqueue(adapter); - - /* Unregister device */ - dev_dbg(adapter->dev, "info: unregister device\n"); - adapter->if_ops.unregister_dev(adapter); - /* Free adapter structure */ - dev_dbg(adapter->dev, "info: free adapter\n"); - mwifiex_free_adapter(adapter); - -exit_remove: - up(sem); -exit_sem_err: - return 0; -} -EXPORT_SYMBOL_GPL(mwifiex_remove_card); - -/* - * This function initializes the module. - * - * The debug FS is also initialized if configured. - */ -static int -mwifiex_init_module(void) -{ -#ifdef CONFIG_DEBUG_FS - mwifiex_debugfs_init(); -#endif - return 0; -} - -/* - * This function cleans up the module. - * - * The debug FS is removed if available. - */ -static void -mwifiex_cleanup_module(void) -{ -#ifdef CONFIG_DEBUG_FS - mwifiex_debugfs_remove(); -#endif -} - -module_init(mwifiex_init_module); -module_exit(mwifiex_cleanup_module); - -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION); -MODULE_VERSION(VERSION); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h deleted file mode 100644 index 1b503038270e..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Marvell Wireless LAN device driver: major data structures and prototypes - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_MAIN_H_ -#define _MWIFIEX_MAIN_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" - -extern const char driver_version[]; -extern struct mwifiex_adapter *g_adapter; - -enum { - MWIFIEX_ASYNC_CMD, - MWIFIEX_SYNC_CMD -}; - -#define DRV_MODE_STA 0x1 - -#define SD8787_W0 0x30 -#define SD8787_W1 0x31 -#define SD8787_A0 0x40 -#define SD8787_A1 0x41 - -#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" -#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin" -#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin" - -struct mwifiex_drv_mode { - u16 drv_mode; - u16 intf_num; - struct mwifiex_bss_attr *bss_attr; -}; - - -#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) - -#define MWIFIEX_TIMER_10S 10000 -#define MWIFIEX_TIMER_1S 1000 - -#define MAX_TX_PENDING 60 - -#define MWIFIEX_UPLD_SIZE (2312) - -#define MAX_EVENT_SIZE 1024 - -#define ARP_FILTER_MAX_BUF_SIZE 68 - -#define MWIFIEX_KEY_BUFFER_SIZE 16 -#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10 -#define MWIFIEX_MAX_REGION_CODE 7 - -#define DEFAULT_BCN_AVG_FACTOR 8 -#define DEFAULT_DATA_AVG_FACTOR 8 - -#define FIRST_VALID_CHANNEL 0xff -#define DEFAULT_AD_HOC_CHANNEL 6 -#define DEFAULT_AD_HOC_CHANNEL_A 36 - -#define DEFAULT_BCN_MISS_TIMEOUT 5 - -#define MAX_SCAN_BEACON_BUFFER 8000 - -#define SCAN_BEACON_ENTRY_PAD 6 - -#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 200 -#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 200 -#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 110 - -#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) - -#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) - -#define RSN_GTK_OUI_OFFSET 2 - -#define MWIFIEX_OUI_NOT_PRESENT 0 -#define MWIFIEX_OUI_PRESENT 1 - -#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ - adapter->event_received || \ - adapter->data_received) - -#define MWIFIEX_TYPE_CMD 1 -#define MWIFIEX_TYPE_DATA 0 -#define MWIFIEX_TYPE_EVENT 3 - -#define DBG_CMD_NUM 5 - -#define MAX_BITMAP_RATES_SIZE 10 - -#define MAX_CHANNEL_BAND_BG 14 - -#define MAX_FREQUENCY_BAND_BG 2484 - -struct mwifiex_dbg { - u32 num_cmd_host_to_card_failure; - u32 num_cmd_sleep_cfm_host_to_card_failure; - u32 num_tx_host_to_card_failure; - u32 num_event_deauth; - u32 num_event_disassoc; - u32 num_event_link_lost; - u32 num_cmd_deauth; - u32 num_cmd_assoc_success; - u32 num_cmd_assoc_failure; - u32 num_tx_timeout; - u32 num_cmd_timeout; - u16 timeout_cmd_id; - u16 timeout_cmd_act; - u16 last_cmd_id[DBG_CMD_NUM]; - u16 last_cmd_act[DBG_CMD_NUM]; - u16 last_cmd_index; - u16 last_cmd_resp_id[DBG_CMD_NUM]; - u16 last_cmd_resp_index; - u16 last_event[DBG_CMD_NUM]; - u16 last_event_index; -}; - -enum MWIFIEX_HARDWARE_STATUS { - MWIFIEX_HW_STATUS_READY, - MWIFIEX_HW_STATUS_INITIALIZING, - MWIFIEX_HW_STATUS_FW_READY, - MWIFIEX_HW_STATUS_INIT_DONE, - MWIFIEX_HW_STATUS_RESET, - MWIFIEX_HW_STATUS_CLOSING, - MWIFIEX_HW_STATUS_NOT_READY -}; - -enum MWIFIEX_802_11_POWER_MODE { - MWIFIEX_802_11_POWER_MODE_CAM, - MWIFIEX_802_11_POWER_MODE_PSP -}; - -struct mwifiex_tx_param { - u32 next_pkt_len; -}; - -enum MWIFIEX_PS_STATE { - PS_STATE_AWAKE, - PS_STATE_PRE_SLEEP, - PS_STATE_SLEEP_CFM, - PS_STATE_SLEEP -}; - -struct mwifiex_add_ba_param { - u32 tx_win_size; - u32 rx_win_size; - u32 timeout; -}; - -struct mwifiex_tx_aggr { - u8 ampdu_user; - u8 ampdu_ap; - u8 amsdu; -}; - -struct mwifiex_ra_list_tbl { - struct list_head list; - struct sk_buff_head skb_head; - u8 ra[ETH_ALEN]; - u32 total_pkts_size; - u32 is_11n_enabled; -}; - -struct mwifiex_tid_tbl { - struct list_head ra_list; - /* spin lock for tid table */ - spinlock_t tid_tbl_lock; - struct mwifiex_ra_list_tbl *ra_list_curr; -}; - -#define WMM_HIGHEST_PRIORITY 7 -#define HIGH_PRIO_TID 7 -#define LOW_PRIO_TID 0 - -struct mwifiex_wmm_desc { - struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; - u32 packets_out[MAX_NUM_TID]; - /* spin lock to protect ra_list */ - spinlock_t ra_list_spinlock; - struct mwifiex_wmm_ac_status ac_status[IEEE80211_MAX_QUEUES]; - enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_MAX_QUEUES]; - u32 drv_pkt_delay_max; - u8 queue_priority[IEEE80211_MAX_QUEUES]; - u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ - -}; - -struct mwifiex_802_11_security { - u8 wpa_enabled; - u8 wpa2_enabled; - u8 wapi_enabled; - u8 wapi_key_on; - enum MWIFIEX_802_11_WEP_STATUS wep_status; - u32 authentication_mode; - u32 encryption_mode; -}; - -struct ieee_types_header { - u8 element_id; - u8 len; -} __packed; - -struct ieee_obss_scan_param { - u16 obss_scan_passive_dwell; - u16 obss_scan_active_dwell; - u16 bss_chan_width_trigger_scan_int; - u16 obss_scan_passive_total; - u16 obss_scan_active_total; - u16 bss_width_chan_trans_delay; - u16 obss_scan_active_threshold; -} __packed; - -struct ieee_types_obss_scan_param { - struct ieee_types_header ieee_hdr; - struct ieee_obss_scan_param obss_scan; -} __packed; - -#define MWIFIEX_SUPPORTED_RATES 14 - -#define MWIFIEX_SUPPORTED_RATES_EXT 32 - -#define IEEE_MAX_IE_SIZE 256 - -struct ieee_types_vendor_specific { - struct ieee_types_vendor_header vend_hdr; - u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; -} __packed; - -struct ieee_types_generic { - struct ieee_types_header ieee_hdr; - u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; -} __packed; - -struct mwifiex_bssdescriptor { - u8 mac_address[ETH_ALEN]; - struct mwifiex_802_11_ssid ssid; - u32 privacy; - s32 rssi; - u32 channel; - u32 freq; - u16 beacon_period; - u8 erp_flags; - u32 bss_mode; - u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; - u8 data_rates[MWIFIEX_SUPPORTED_RATES]; - /* Network band. - * BAND_B(0x01): 'b' band - * BAND_G(0x02): 'g' band - * BAND_A(0X04): 'a' band - */ - u16 bss_band; - long long network_tsf; - u8 time_stamp[8]; - union ieee_types_phy_param_set phy_param_set; - union ieee_types_ss_param_set ss_param_set; - u16 cap_info_bitmap; - struct ieee_types_wmm_parameter wmm_ie; - u8 disable_11n; - struct ieee80211_ht_cap *bcn_ht_cap; - u16 ht_cap_offset; - struct ieee80211_ht_info *bcn_ht_info; - u16 ht_info_offset; - u8 *bcn_bss_co_2040; - u16 bss_co_2040_offset; - u8 *bcn_ext_cap; - u16 ext_cap_offset; - struct ieee_types_obss_scan_param *bcn_obss_scan; - u16 overlap_bss_offset; - struct ieee_types_vendor_specific *bcn_wpa_ie; - u16 wpa_offset; - struct ieee_types_generic *bcn_rsn_ie; - u16 rsn_offset; - struct ieee_types_generic *bcn_wapi_ie; - u16 wapi_offset; - u8 *beacon_buf; - u32 beacon_buf_size; - u32 beacon_buf_size_max; - -}; - -struct mwifiex_current_bss_params { - struct mwifiex_bssdescriptor bss_descriptor; - u8 wmm_enabled; - u8 wmm_uapsd_enabled; - u8 band; - u32 num_of_rates; - u8 data_rates[MWIFIEX_SUPPORTED_RATES]; -}; - -struct mwifiex_sleep_params { - u16 sp_error; - u16 sp_offset; - u16 sp_stable_time; - u8 sp_cal_control; - u8 sp_ext_sleep_clk; - u16 sp_reserved; -}; - -struct mwifiex_sleep_period { - u16 period; - u16 reserved; -}; - -struct mwifiex_wep_key { - u32 length; - u32 key_index; - u32 key_length; - u8 key_material[MWIFIEX_KEY_BUFFER_SIZE]; -}; - -#define MAX_REGION_CHANNEL_NUM 2 - -struct mwifiex_chan_freq_power { - u16 channel; - u32 freq; - u16 max_tx_power; - u8 unsupported; -}; - -enum state_11d_t { - DISABLE_11D = 0, - ENABLE_11D = 1, -}; - -#define MWIFIEX_MAX_TRIPLET_802_11D 83 - -struct mwifiex_802_11d_domain_reg { - u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; - u8 no_of_triplet; - struct ieee80211_country_ie_triplet - triplet[MWIFIEX_MAX_TRIPLET_802_11D]; -}; - -struct mwifiex_vendor_spec_cfg_ie { - u16 mask; - u16 flag; - u8 ie[MWIFIEX_MAX_VSIE_LEN]; -}; - -struct wps { - u8 session_enable; -}; - -struct mwifiex_adapter; -struct mwifiex_private; - -struct mwifiex_private { - struct mwifiex_adapter *adapter; - u8 bss_index; - u8 bss_type; - u8 bss_role; - u8 bss_priority; - u8 bss_num; - u8 frame_type; - u8 curr_addr[ETH_ALEN]; - u8 media_connected; - u32 num_tx_timeout; - struct net_device *netdev; - struct net_device_stats stats; - u16 curr_pkt_filter; - u32 bss_mode; - u32 pkt_tx_ctrl; - u16 tx_power_level; - u8 max_tx_power_level; - u8 min_tx_power_level; - u8 tx_rate; - u8 tx_htinfo; - u8 rxpd_htinfo; - u8 rxpd_rate; - u16 rate_bitmap; - u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; - u32 data_rate; - u8 is_data_rate_auto; - u16 bcn_avg_factor; - u16 data_avg_factor; - s16 data_rssi_last; - s16 data_nf_last; - s16 data_rssi_avg; - s16 data_nf_avg; - s16 bcn_rssi_last; - s16 bcn_nf_last; - s16 bcn_rssi_avg; - s16 bcn_nf_avg; - struct mwifiex_bssdescriptor *attempted_bss_desc; - struct mwifiex_802_11_ssid prev_ssid; - u8 prev_bssid[ETH_ALEN]; - struct mwifiex_current_bss_params curr_bss_params; - u16 beacon_period; - u16 listen_interval; - u16 atim_window; - u8 adhoc_channel; - u8 adhoc_is_link_sensed; - u8 adhoc_state; - struct mwifiex_802_11_security sec_info; - struct mwifiex_wep_key wep_key[NUM_WEP_KEYS]; - u16 wep_key_curr_index; - u8 wpa_ie[256]; - u8 wpa_ie_len; - u8 wpa_is_gtk_set; - struct host_cmd_ds_802_11_key_material aes_key; - u8 wapi_ie[256]; - u8 wapi_ie_len; - u8 wmm_required; - u8 wmm_enabled; - u8 wmm_qosinfo; - struct mwifiex_wmm_desc wmm; - struct list_head tx_ba_stream_tbl_ptr; - /* spin lock for tx_ba_stream_tbl_ptr queue */ - spinlock_t tx_ba_stream_tbl_lock; - struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; - struct mwifiex_add_ba_param add_ba_param; - u16 rx_seq[MAX_NUM_TID]; - struct list_head rx_reorder_tbl_ptr; - /* spin lock for rx_reorder_tbl_ptr queue */ - spinlock_t rx_reorder_tbl_lock; - /* spin lock for Rx packets */ - spinlock_t rx_pkt_lock; - -#define MWIFIEX_ASSOC_RSP_BUF_SIZE 500 - u8 assoc_rsp_buf[MWIFIEX_ASSOC_RSP_BUF_SIZE]; - u32 assoc_rsp_size; - -#define MWIFIEX_GENIE_BUF_SIZE 256 - u8 gen_ie_buf[MWIFIEX_GENIE_BUF_SIZE]; - u8 gen_ie_buf_len; - - struct mwifiex_vendor_spec_cfg_ie vs_ie[MWIFIEX_MAX_VSIE_NUM]; - -#define MWIFIEX_ASSOC_TLV_BUF_SIZE 256 - u8 assoc_tlv_buf[MWIFIEX_ASSOC_TLV_BUF_SIZE]; - u8 assoc_tlv_buf_len; - - u8 *curr_bcn_buf; - u32 curr_bcn_size; - /* spin lock for beacon buffer */ - spinlock_t curr_bcn_buf_lock; - struct wireless_dev *wdev; - struct mwifiex_chan_freq_power cfp; - char version_str[128]; -#ifdef CONFIG_DEBUG_FS - struct dentry *dfs_dev_dir; -#endif - u8 nick_name[16]; - struct iw_statistics w_stats; - u16 current_key_index; - struct semaphore async_sem; - u8 scan_pending_on_block; - u8 report_scan_result; - struct cfg80211_scan_request *scan_request; - int scan_result_status; - bool assoc_request; - u16 assoc_result; - bool ibss_join_request; - u16 ibss_join_result; - bool disconnect; - u8 cfg_bssid[6]; - struct workqueue_struct *workqueue; - struct work_struct cfg_workqueue; - u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; - struct wps wps; - u8 scan_block; -}; - -enum mwifiex_ba_status { - BA_STREAM_NOT_SETUP = 0, - BA_STREAM_SETUP_INPROGRESS, - BA_STREAM_SETUP_COMPLETE -}; - -struct mwifiex_tx_ba_stream_tbl { - struct list_head list; - int tid; - u8 ra[ETH_ALEN]; - enum mwifiex_ba_status ba_status; -}; - -struct mwifiex_rx_reorder_tbl; - -struct reorder_tmr_cnxt { - struct timer_list timer; - struct mwifiex_rx_reorder_tbl *ptr; - struct mwifiex_private *priv; -}; - -struct mwifiex_rx_reorder_tbl { - struct list_head list; - int tid; - u8 ta[ETH_ALEN]; - int start_win; - int win_size; - void **rx_reorder_ptr; - struct reorder_tmr_cnxt timer_context; -}; - -struct mwifiex_bss_prio_node { - struct list_head list; - struct mwifiex_private *priv; -}; - -struct mwifiex_bss_prio_tbl { - struct list_head bss_prio_head; - /* spin lock for bss priority */ - spinlock_t bss_prio_lock; - struct mwifiex_bss_prio_node *bss_prio_cur; -}; - -struct cmd_ctrl_node { - struct list_head list; - struct mwifiex_private *priv; - u32 cmd_oid; - u32 cmd_flag; - struct sk_buff *cmd_skb; - struct sk_buff *resp_skb; - void *data_buf; - u32 wait_q_enabled; - struct sk_buff *skb; -}; - -struct mwifiex_if_ops { - int (*init_if) (struct mwifiex_adapter *); - void (*cleanup_if) (struct mwifiex_adapter *); - int (*check_fw_status) (struct mwifiex_adapter *, u32, int *); - int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); - int (*register_dev) (struct mwifiex_adapter *); - void (*unregister_dev) (struct mwifiex_adapter *); - int (*enable_int) (struct mwifiex_adapter *); - int (*process_int_status) (struct mwifiex_adapter *); - int (*host_to_card) (struct mwifiex_adapter *, u8, - u8 *payload, u32 pkt_len, - struct mwifiex_tx_param *); - int (*wakeup) (struct mwifiex_adapter *); - int (*wakeup_complete) (struct mwifiex_adapter *); - - void (*update_mp_end_port) (struct mwifiex_adapter *, u16); - void (*cleanup_mpa_buf) (struct mwifiex_adapter *); -}; - -struct mwifiex_adapter { - struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; - u8 priv_num; - struct mwifiex_drv_mode *drv_mode; - const struct firmware *firmware; - struct device *dev; - bool surprise_removed; - u32 fw_release_number; - u32 revision_id; - u16 init_wait_q_woken; - wait_queue_head_t init_wait_q; - void *card; - struct mwifiex_if_ops if_ops; - atomic_t rx_pending; - atomic_t tx_pending; - atomic_t cmd_pending; - struct workqueue_struct *workqueue; - struct work_struct main_work; - struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; - /* spin lock for init/shutdown */ - spinlock_t mwifiex_lock; - /* spin lock for main process */ - spinlock_t main_proc_lock; - u32 mwifiex_processing; - u16 max_tx_buf_size; - u16 tx_buf_size; - u16 curr_tx_buf_size; - u32 ioport; - enum MWIFIEX_HARDWARE_STATUS hw_status; - u16 number_of_antenna; - u32 fw_cap_info; - /* spin lock for interrupt handling */ - spinlock_t int_lock; - u8 int_status; - u32 event_cause; - struct sk_buff *event_skb; - u8 upld_buf[MWIFIEX_UPLD_SIZE]; - u8 data_sent; - u8 cmd_sent; - u8 cmd_resp_received; - u8 event_received; - u8 data_received; - u16 seq_num; - struct cmd_ctrl_node *cmd_pool; - struct cmd_ctrl_node *curr_cmd; - /* spin lock for command */ - spinlock_t mwifiex_cmd_lock; - u32 num_cmd_timeout; - u16 last_init_cmd; - struct timer_list cmd_timer; - struct list_head cmd_free_q; - /* spin lock for cmd_free_q */ - spinlock_t cmd_free_q_lock; - struct list_head cmd_pending_q; - /* spin lock for cmd_pending_q */ - spinlock_t cmd_pending_q_lock; - struct list_head scan_pending_q; - /* spin lock for scan_pending_q */ - spinlock_t scan_pending_q_lock; - u32 scan_processing; - u16 region_code; - struct mwifiex_802_11d_domain_reg domain_reg; - struct mwifiex_bssdescriptor *scan_table; - u32 num_in_scan_table; - u16 scan_probes; - u32 scan_mode; - u16 specific_scan_time; - u16 active_scan_time; - u16 passive_scan_time; - u8 bcn_buf[MAX_SCAN_BEACON_BUFFER]; - u8 *bcn_buf_end; - u8 fw_bands; - u8 adhoc_start_band; - u8 config_bands; - struct mwifiex_chan_scan_param_set *scan_channels; - u8 tx_lock_flag; - struct mwifiex_sleep_params sleep_params; - struct mwifiex_sleep_period sleep_period; - u16 ps_mode; - u32 ps_state; - u8 need_to_wakeup; - u16 multiple_dtim; - u16 local_listen_interval; - u16 null_pkt_interval; - struct sk_buff *sleep_cfm; - u16 bcn_miss_time_out; - u16 adhoc_awake_period; - u8 is_deep_sleep; - u8 delay_null_pkt; - u16 delay_to_ps; - u16 enhanced_ps_mode; - u8 pm_wakeup_card_req; - u16 gen_null_pkt; - u16 pps_uapsd_mode; - u32 pm_wakeup_fw_try; - u8 is_hs_configured; - struct mwifiex_hs_config_param hs_cfg; - u8 hs_activated; - u16 hs_activate_wait_q_woken; - wait_queue_head_t hs_activate_wait_q; - bool is_suspended; - u8 event_body[MAX_EVENT_SIZE]; - u32 hw_dot_11n_dev_cap; - u8 hw_dev_mcs_support; - u8 adhoc_11n_enabled; - u8 chan_offset; - struct mwifiex_dbg dbg; - u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; - u32 arp_filter_size; - u16 cmd_wait_q_required; - struct mwifiex_wait_queue cmd_wait_q; -}; - -int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); -void mwifiex_free_lock_list(struct mwifiex_adapter *adapter); - -int mwifiex_init_fw(struct mwifiex_adapter *adapter); - -int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); - -int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter); - -int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); - -int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); - -int mwifiex_recv_complete(struct mwifiex_adapter *, - struct sk_buff *skb, - int status); - -int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); - -int mwifiex_process_event(struct mwifiex_adapter *adapter); - -int mwifiex_complete_cmd(struct mwifiex_adapter *adapter); - -int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, void *data_buf); - -int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, void *data_buf); - -void mwifiex_cmd_timeout_func(unsigned long function_context); - -int mwifiex_get_debug_info(struct mwifiex_private *, - struct mwifiex_debug_info *); - -int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter); -int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter); -void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); -void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); - -void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node); - -void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node, - u32 addtail); - -int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter); -int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter); -int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb); -int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, - struct mwifiex_tx_param *tx_param); -int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); -int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int status); -int mwifiex_recv_packet_complete(struct mwifiex_adapter *, - struct sk_buff *skb, int status); -void mwifiex_clean_txrx(struct mwifiex_private *priv); -u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); -void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter); -void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *, - u32); -int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, uint16_t ps_bitmap, - void *data_buf); -int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf); -void mwifiex_process_hs_config(struct mwifiex_adapter *adapter); -void mwifiex_hs_activated_event(struct mwifiex_private *priv, - u8 activated); -int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb); -int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *data_buf, void *cmd_buf); -int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, - void *cmd_buf); -int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, - struct sk_buff *skb); -int mwifiex_process_sta_event(struct mwifiex_private *); -void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); -int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); -int mwifiex_scan_networks(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg *user_scan_in); -int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, - void *data_buf); -void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node); -int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *ssid, u8 *bssid, - u32 mode); -s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, - u32 mode); -int mwifiex_find_best_network(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *req_ssid_bssid); -s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, - struct mwifiex_802_11_ssid *ssid2); -int mwifiex_associate(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command - *cmd, void *data_buf); -int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -void mwifiex_reset_connect_state(struct mwifiex_private *priv); -void mwifiex_2040_coex_event(struct mwifiex_private *priv); -u8 mwifiex_band_to_radio_type(u8 band); -int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); -int mwifiex_adhoc_start(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *adhoc_ssid); -int mwifiex_adhoc_join(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf); -int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf); -int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); -struct mwifiex_chan_freq_power * - mwifiex_get_cfp_by_band_and_channel_from_cfg80211( - struct mwifiex_private *priv, - u8 band, u16 channel); -struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211( - struct mwifiex_private *priv, - u8 band, u32 freq); -u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info); -u32 mwifiex_find_freq_from_band_chan(u8, u8); -int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, - u8 **buffer); -u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, - u8 *rates); -u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates); -u8 mwifiex_data_rate_to_index(u32 rate); -u8 mwifiex_is_rate_auto(struct mwifiex_private *priv); -int mwifiex_get_rate_index(u16 *rateBitmap, int size); -extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE]; -void mwifiex_save_curr_bcn(struct mwifiex_private *priv); -void mwifiex_free_curr_bcn(struct mwifiex_private *priv); -int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd); -int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int is_command_pending(struct mwifiex_adapter *adapter); - -/* - * This function checks if the queuing is RA based or not. - */ -static inline u8 -mwifiex_queuing_ra_based(struct mwifiex_private *priv) -{ - /* - * Currently we assume if we are in Infra, then DA=RA. This might not be - * true in the future - */ - if ((priv->bss_mode == NL80211_IFTYPE_STATION) && - (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)) - return false; - - return true; -} - -/* - * This function copies rates. - */ -static inline u32 -mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len) -{ - int i; - - for (i = 0; i < len && src[i]; i++, pos++) { - if (pos >= MWIFIEX_SUPPORTED_RATES) - break; - dest[pos] = src[i]; - } - - return pos; -} - -/* - * This function returns the correct private structure pointer based - * upon the BSS type and BSS number. - */ -static inline struct mwifiex_private * -mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter, - u8 bss_num, u8 bss_type) -{ - int i; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - if ((adapter->priv[i]->bss_num == bss_num) - && (adapter->priv[i]->bss_type == bss_type)) - break; - } - } - return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -} - -/* - * This function returns the first available private structure pointer - * based upon the BSS role. - */ -static inline struct mwifiex_private * -mwifiex_get_priv(struct mwifiex_adapter *adapter, - enum mwifiex_bss_role bss_role) -{ - int i; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - if (bss_role == MWIFIEX_BSS_ROLE_ANY || - GET_BSS_ROLE(adapter->priv[i]) == bss_role) - break; - } - } - - return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -} - -/* - * This function returns the driver private structure of a network device. - */ -static inline struct mwifiex_private * -mwifiex_netdev_get_priv(struct net_device *dev) -{ - return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); -} - -struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter - *adapter, u8 bss_index); -int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, - u32 func_init_shutdown); -int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *); -int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *); - -void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version, - int maxlen); -int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, - struct mwifiex_multicast_list *mcast_list); -int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, - struct net_device *dev); -int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); -int mwifiex_bss_start(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *ssid_bssid); -int mwifiex_set_hs_params(struct mwifiex_private *priv, - u16 action, int cmd_type, - struct mwifiex_ds_hs_cfg *hscfg); -int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); -int mwifiex_enable_hs(struct mwifiex_adapter *adapter); -int mwifiex_get_signal_info(struct mwifiex_private *priv, - struct mwifiex_ds_get_signal *signal); -int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, - struct mwifiex_rate_cfg *rate); -int mwifiex_find_best_bss(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *ssid_bssid); -int mwifiex_request_scan(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *req_ssid); -int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, - struct mwifiex_user_scan_cfg *scan_req); -int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel); -int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); - -int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel); - -int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, - int key_len, u8 key_index, int disable); - -int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); - -int mwifiex_get_ver_ext(struct mwifiex_private *priv); - -int mwifiex_get_stats_info(struct mwifiex_private *priv, - struct mwifiex_ds_get_stats *log); - -int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 reg_value); - -int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 *value); - -int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, - u8 *value); - -int mwifiex_set_11n_httx_cfg(struct mwifiex_private *priv, int data); - -int mwifiex_get_11n_httx_cfg(struct mwifiex_private *priv, int *data); - -int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index); - -int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index); - -int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode); - -int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, - char *version, int max_len); - -int mwifiex_set_tx_power(struct mwifiex_private *priv, - struct mwifiex_power_cfg *power_cfg); - -int mwifiex_main_process(struct mwifiex_adapter *); - -int mwifiex_bss_set_channel(struct mwifiex_private *, - struct mwifiex_chan_freq_power *cfp); -int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *, - struct mwifiex_ssid_bssid *); -int mwifiex_set_radio_band_cfg(struct mwifiex_private *, - struct mwifiex_ds_band_cfg *); -int mwifiex_get_bss_info(struct mwifiex_private *, - struct mwifiex_bss_info *); - -#ifdef CONFIG_DEBUG_FS -void mwifiex_debugfs_init(void); -void mwifiex_debugfs_remove(void); - -void mwifiex_dev_debugfs_init(struct mwifiex_private *priv); -void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv); -#endif -#endif /* !_MWIFIEX_MAIN_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/scan.c b/trunk/drivers/net/wireless/mwifiex/scan.c deleted file mode 100644 index 31a529578805..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/scan.c +++ /dev/null @@ -1,3025 +0,0 @@ -/* - * Marvell Wireless LAN device driver: scan ioctl and command handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "11n.h" -#include "cfg80211.h" - -/* The maximum number of channels the firmware can scan per command */ -#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 - -#define MWIFIEX_CHANNELS_PER_SCAN_CMD 4 - -/* Memory needed to store a max sized Channel List TLV for a firmware scan */ -#define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ - + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN \ - *sizeof(struct mwifiex_chan_scan_param_set))) - -/* Memory needed to store supported rate */ -#define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \ - + HOSTCMD_SUPPORTED_RATES) - -/* Memory needed to store a max number/size WildCard SSID TLV for a firmware - scan */ -#define WILDCARD_SSID_TLV_MAX_SIZE \ - (MWIFIEX_MAX_SSID_LIST_LENGTH * \ - (sizeof(struct mwifiex_ie_types_wildcard_ssid_params) \ - + IEEE80211_MAX_SSID_LEN)) - -/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */ -#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config) \ - + sizeof(struct mwifiex_ie_types_num_probes) \ - + sizeof(struct mwifiex_ie_types_htcap) \ - + CHAN_TLV_MAX_SIZE \ - + RATE_TLV_MAX_SIZE \ - + WILDCARD_SSID_TLV_MAX_SIZE) - - -union mwifiex_scan_cmd_config_tlv { - /* Scan configuration (variable length) */ - struct mwifiex_scan_cmd_config config; - /* Max allocated block */ - u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC]; -}; - -enum cipher_suite { - CIPHER_SUITE_TKIP, - CIPHER_SUITE_CCMP, - CIPHER_SUITE_MAX -}; -static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = { - { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */ - { 0x00, 0x50, 0xf2, 0x04 }, /* AES */ -}; -static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { - { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */ - { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ -}; - -/* - * This function parses a given IE for a given OUI. - * - * This is used to parse a WPA/RSN IE to find if it has - * a given oui in PTK. - */ -static u8 -mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) -{ - u8 count; - - count = iebody->ptk_cnt[0]; - - /* There could be multiple OUIs for PTK hence - 1) Take the length. - 2) Check all the OUIs for AES. - 3) If one of them is AES then pass success. */ - while (count) { - if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body))) - return MWIFIEX_OUI_PRESENT; - - --count; - if (count) - iebody = (struct ie_body *) ((u8 *) iebody + - sizeof(iebody->ptk_body)); - } - - pr_debug("info: %s: OUI is not found in PTK\n", __func__); - return MWIFIEX_OUI_NOT_PRESENT; -} - -/* - * This function checks if a given OUI is present in a RSN IE. - * - * The function first checks if a RSN IE is present or not in the - * BSS descriptor. It tries to locate the OUI only if such an IE is - * present. - */ -static u8 -mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) -{ - u8 *oui = NULL; - struct ie_body *iebody = NULL; - u8 ret = MWIFIEX_OUI_NOT_PRESENT; - - if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id == WLAN_EID_RSN))) { - iebody = (struct ie_body *) - (((u8 *) bss_desc->bcn_rsn_ie->data) + - RSN_GTK_OUI_OFFSET); - oui = &mwifiex_rsn_oui[cipher][0]; - ret = mwifiex_search_oui_in_ie(iebody, oui); - if (ret) - return ret; - } - return ret; -} - -/* - * This function checks if a given OUI is present in a WPA IE. - * - * The function first checks if a WPA IE is present or not in the - * BSS descriptor. It tries to locate the OUI only if such an IE is - * present. - */ -static u8 -mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) -{ - u8 *oui = NULL; - struct ie_body *iebody = NULL; - u8 ret = MWIFIEX_OUI_NOT_PRESENT; - - if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id == WLAN_EID_WPA))) { - iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; - oui = &mwifiex_wpa_oui[cipher][0]; - ret = mwifiex_search_oui_in_ie(iebody, oui); - if (ret) - return ret; - } - return ret; -} - -/* - * This function compares two SSIDs and checks if they match. - */ -s32 -mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, - struct mwifiex_802_11_ssid *ssid2) -{ - if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len)) - return -1; - return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len); -} - -/* - * Sends IOCTL request to get the best BSS. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_find_best_bss(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *ssid_bssid) -{ - struct mwifiex_ssid_bssid tmp_ssid_bssid; - u8 *mac = NULL; - - if (!ssid_bssid) - return -1; - - memcpy(&tmp_ssid_bssid, ssid_bssid, - sizeof(struct mwifiex_ssid_bssid)); - - if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) { - memcpy(ssid_bssid, &tmp_ssid_bssid, - sizeof(struct mwifiex_ssid_bssid)); - mac = (u8 *) &ssid_bssid->bssid; - dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s," - " %pM\n", ssid_bssid->ssid.ssid, mac); - return 0; - } - - return -1; -} - -/* - * Sends IOCTL request to start a scan with user configurations. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - * - * Upon completion, it also generates a wireless event to notify - * applications. - */ -int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, - struct mwifiex_user_scan_cfg *scan_req) -{ - int status = 0; - - priv->adapter->cmd_wait_q.condition = false; - - status = mwifiex_scan_networks(priv, scan_req); - if (!status) - status = mwifiex_wait_queue_complete(priv->adapter); - - return status; -} - -/* - * This function checks if wapi is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_wapi(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (priv->sec_info.wapi_enabled && - (bss_desc->bcn_wapi_ie && - ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id == - WLAN_EID_BSS_AC_ACCESS_DELAY))) { - return true; - } - return false; -} - -/* - * This function checks if driver is configured with no security mode and - * scanned network is compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_no_sec(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED - && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled - && ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != - WLAN_EID_WPA)) - && ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != - WLAN_EID_RSN)) - && !priv->sec_info.encryption_mode - && !bss_desc->privacy) { - return true; - } - return false; -} - -/* - * This function checks if static WEP is enabled in driver and scanned network - * is compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED - && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled - && bss_desc->privacy) { - return true; - } - return false; -} - -/* - * This function checks if wpa is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - int index) -{ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED - && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled - && ((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)).vend_hdr. - element_id == WLAN_EID_WPA)) - /* - * Privacy bit may NOT be set in some APs like - * LinkSys WRT54G && bss_desc->privacy - */ - ) { - dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d" - " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " - "EncMode=%#x privacy=%#x\n", __func__, index, - (bss_desc->bcn_wpa_ie) ? - (*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id : 0, - (priv->sec_info.wep_status == - MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); - return true; - } - return false; -} - -/* - * This function checks if wpa2 is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - int index) -{ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED - && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled - && ((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. - element_id == WLAN_EID_RSN)) - /* - * Privacy bit may NOT be set in some APs like - * LinkSys WRT54G && bss_desc->privacy - */ - ) { - dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d" - " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " - "EncMode=%#x privacy=%#x\n", __func__, index, - (bss_desc->bcn_wpa_ie) ? - (*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id : 0, - (priv->sec_info.wep_status == - MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); - return true; - } - return false; -} - -/* - * This function checks if adhoc AES is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED - && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled - && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr. - element_id != WLAN_EID_WPA)) - && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. - element_id != WLAN_EID_RSN)) - && !priv->sec_info.encryption_mode - && bss_desc->privacy) { - return true; - } - return false; -} - -/* - * This function checks if dynamic WEP is enabled in driver and scanned network - * is compatible with it. - */ -static bool -mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - int index) -{ - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED - && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled - && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr. - element_id != WLAN_EID_WPA)) - && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. - element_id != WLAN_EID_RSN)) - && priv->sec_info.encryption_mode - && bss_desc->privacy) { - dev_dbg(priv->adapter->dev, "info: %s: dynamic " - "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " - "EncMode=%#x privacy=%#x\n", - __func__, index, - (bss_desc->bcn_wpa_ie) ? - (*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id : 0, - priv->sec_info.encryption_mode, - bss_desc->privacy); - return true; - } - return false; -} - -/* - * This function checks if a scanned network is compatible with the driver - * settings. - * - * WEP WPA WPA2 ad-hoc encrypt Network - * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible - * 0 0 0 0 NONE 0 0 0 yes No security - * 0 1 0 0 x 1x 1 x yes WPA (disable - * HT if no AES) - * 0 0 1 0 x 1x x 1 yes WPA2 (disable - * HT if no AES) - * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES - * 1 0 0 0 NONE 1 0 0 yes Static WEP - * (disable HT) - * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP - * - * Compatibility is not matched while roaming, except for mode. - */ -static s32 -mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *bss_desc; - - bss_desc = &adapter->scan_table[index]; - bss_desc->disable_11n = false; - - /* Don't check for compatibility if roaming */ - if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION) - && (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) - return index; - - if (priv->wps.session_enable) { - dev_dbg(adapter->dev, - "info: return success directly in WPS period\n"); - return index; - } - - if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) { - dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); - return index; - } - - if (bss_desc->bss_mode == mode) { - if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) { - /* No security */ - return index; - } else if (mwifiex_is_network_compatible_for_static_wep(priv, - bss_desc)) { - /* Static WEP enabled */ - dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n"); - bss_desc->disable_11n = true; - return index; - } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc, - index)) { - /* WPA enabled */ - if (((priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN) - && bss_desc->bcn_ht_cap) - && !mwifiex_is_wpa_oui_present(bss_desc, - CIPHER_SUITE_CCMP)) { - - if (mwifiex_is_wpa_oui_present(bss_desc, - CIPHER_SUITE_TKIP)) { - dev_dbg(adapter->dev, - "info: Disable 11n if AES " - "is not supported by AP\n"); - bss_desc->disable_11n = true; - } else { - return -1; - } - } - return index; - } else if (mwifiex_is_network_compatible_for_wpa2(priv, - bss_desc, index)) { - /* WPA2 enabled */ - if (((priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN) - && bss_desc->bcn_ht_cap) - && !mwifiex_is_rsn_oui_present(bss_desc, - CIPHER_SUITE_CCMP)) { - - if (mwifiex_is_rsn_oui_present(bss_desc, - CIPHER_SUITE_TKIP)) { - dev_dbg(adapter->dev, - "info: Disable 11n if AES " - "is not supported by AP\n"); - bss_desc->disable_11n = true; - } else { - return -1; - } - } - return index; - } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv, - bss_desc)) { - /* Ad-hoc AES enabled */ - return index; - } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv, - bss_desc, index)) { - /* Dynamic WEP enabled */ - return index; - } - - /* Security doesn't match */ - dev_dbg(adapter->dev, "info: %s: failed: index=%d " - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode" - "=%#x privacy=%#x\n", - __func__, index, - (bss_desc->bcn_wpa_ie) ? - (*(bss_desc->bcn_wpa_ie)).vend_hdr. - element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*(bss_desc->bcn_rsn_ie)).ieee_hdr. - element_id : 0, - (priv->sec_info.wep_status == - MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, bss_desc->privacy); - return -1; - } - - /* Mode doesn't match */ - return -1; -} - -/* - * This function finds the best SSID in the scan list. - * - * It searches the scan table for the best SSID that also matches the current - * adapter network preference (mode, security etc.). - */ -static s32 -mwifiex_find_best_network_in_list(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u32 mode = priv->bss_mode; - s32 best_net = -1; - s32 best_rssi = 0; - u32 i; - - dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n", - adapter->num_in_scan_table); - - for (i = 0; i < adapter->num_in_scan_table; i++) { - switch (mode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - if (mwifiex_is_network_compatible(priv, i, mode) >= 0) { - if (SCAN_RSSI(adapter->scan_table[i].rssi) > - best_rssi) { - best_rssi = SCAN_RSSI(adapter-> - scan_table[i].rssi); - best_net = i; - } - } - break; - case NL80211_IFTYPE_UNSPECIFIED: - default: - if (SCAN_RSSI(adapter->scan_table[i].rssi) > - best_rssi) { - best_rssi = SCAN_RSSI(adapter->scan_table[i]. - rssi); - best_net = i; - } - break; - } - } - - return best_net; -} - -/* - * This function creates a channel list for the driver to scan, based - * on region/band information. - * - * This routine is used for any scan that is not provided with a - * specific channel list to scan. - */ -static void -mwifiex_scan_create_channel_list(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg - *user_scan_in, - struct mwifiex_chan_scan_param_set - *scan_chan_list, - u8 filtered_scan) -{ - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - struct mwifiex_adapter *adapter = priv->adapter; - int chan_idx = 0, i; - u8 scan_type; - - for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { - - if (!priv->wdev->wiphy->bands[band]) - continue; - - sband = priv->wdev->wiphy->bands[band]; - - for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) { - ch = &sband->channels[i]; - if (ch->flags & IEEE80211_CHAN_DISABLED) - continue; - scan_chan_list[chan_idx].radio_type = band; - scan_type = ch->flags & IEEE80211_CHAN_PASSIVE_SCAN; - if (user_scan_in && - user_scan_in->chan_list[0].scan_time) - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16((u16) user_scan_in-> - chan_list[0].scan_time); - else if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->passive_scan_time); - else - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->active_scan_time); - if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_PASSIVE_SCAN; - else - scan_chan_list[chan_idx].chan_scan_mode_bitmap - &= ~MWIFIEX_PASSIVE_SCAN; - scan_chan_list[chan_idx].chan_number = - (u32) ch->hw_value; - if (filtered_scan) { - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->specific_scan_time); - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; - } - } - - } -} - -/* - * This function constructs and sends multiple scan config commands to - * the firmware. - * - * Previous routines in the code flow have created a scan command configuration - * with any requested TLVs. This function splits the channel TLV into maximum - * channels supported per scan lists and sends the portion of the channel TLV, - * along with the other TLVs, to the firmware. - */ -static int -mwifiex_scan_channel_list(struct mwifiex_private *priv, - u32 max_chan_per_scan, u8 filtered_scan, - struct mwifiex_scan_cmd_config *scan_cfg_out, - struct mwifiex_ie_types_chan_list_param_set - *chan_tlv_out, - struct mwifiex_chan_scan_param_set *scan_chan_list) -{ - int ret = 0; - struct mwifiex_chan_scan_param_set *tmp_chan_list; - struct mwifiex_chan_scan_param_set *start_chan; - - u32 tlv_idx; - u32 total_scan_time; - u32 done_early; - - if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) { - dev_dbg(priv->adapter->dev, - "info: Scan: Null detect: %p, %p, %p\n", - scan_cfg_out, chan_tlv_out, scan_chan_list); - return -1; - } - - chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - - /* Set the temp channel struct pointer to the start of the desired - list */ - tmp_chan_list = scan_chan_list; - - /* Loop through the desired channel list, sending a new firmware scan - commands for each max_chan_per_scan channels (or for 1,6,11 - individually if configured accordingly) */ - while (tmp_chan_list->chan_number) { - - tlv_idx = 0; - total_scan_time = 0; - chan_tlv_out->header.len = 0; - start_chan = tmp_chan_list; - done_early = false; - - /* - * Construct the Channel TLV for the scan command. Continue to - * insert channel TLVs until: - * - the tlv_idx hits the maximum configured per scan command - * - the next channel to insert is 0 (end of desired channel - * list) - * - done_early is set (controlling individual scanning of - * 1,6,11) - */ - while (tlv_idx < max_chan_per_scan - && tmp_chan_list->chan_number && !done_early) { - - dev_dbg(priv->adapter->dev, - "info: Scan: Chan(%3d), Radio(%d)," - " Mode(%d, %d), Dur(%d)\n", - tmp_chan_list->chan_number, - tmp_chan_list->radio_type, - tmp_chan_list->chan_scan_mode_bitmap - & MWIFIEX_PASSIVE_SCAN, - (tmp_chan_list->chan_scan_mode_bitmap - & MWIFIEX_DISABLE_CHAN_FILT) >> 1, - le16_to_cpu(tmp_chan_list->max_scan_time)); - - /* Copy the current channel TLV to the command being - prepared */ - memcpy(chan_tlv_out->chan_scan_param + tlv_idx, - tmp_chan_list, - sizeof(chan_tlv_out->chan_scan_param)); - - /* Increment the TLV header length by the size - appended */ - chan_tlv_out->header.len = - cpu_to_le16(le16_to_cpu(chan_tlv_out->header.len) + - (sizeof(chan_tlv_out->chan_scan_param))); - - /* - * The tlv buffer length is set to the number of bytes - * of the between the channel tlv pointer and the start - * of the tlv buffer. This compensates for any TLVs - * that were appended before the channel list. - */ - scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out - - scan_cfg_out->tlv_buf); - - /* Add the size of the channel tlv header and the data - length */ - scan_cfg_out->tlv_buf_len += - (sizeof(chan_tlv_out->header) - + le16_to_cpu(chan_tlv_out->header.len)); - - /* Increment the index to the channel tlv we are - constructing */ - tlv_idx++; - - /* Count the total scan time per command */ - total_scan_time += - le16_to_cpu(tmp_chan_list->max_scan_time); - - done_early = false; - - /* Stop the loop if the *current* channel is in the - 1,6,11 set and we are not filtering on a BSSID - or SSID. */ - if (!filtered_scan && (tmp_chan_list->chan_number == 1 - || tmp_chan_list->chan_number == 6 - || tmp_chan_list->chan_number == 11)) - done_early = true; - - /* Increment the tmp pointer to the next channel to - be scanned */ - tmp_chan_list++; - - /* Stop the loop if the *next* channel is in the 1,6,11 - set. This will cause it to be the only channel - scanned on the next interation */ - if (!filtered_scan && (tmp_chan_list->chan_number == 1 - || tmp_chan_list->chan_number == 6 - || tmp_chan_list->chan_number == 11)) - done_early = true; - } - - /* The total scan time should be less than scan command timeout - value */ - if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) { - dev_err(priv->adapter->dev, "total scan time %dms" - " is over limit (%dms), scan skipped\n", - total_scan_time, MWIFIEX_MAX_TOTAL_SCAN_TIME); - ret = -1; - break; - } - - priv->adapter->scan_channels = start_chan; - - /* Send the scan command to the firmware with the specified - cfg */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, - HostCmd_ACT_GEN_SET, 0, - scan_cfg_out); - if (ret) - break; - } - - if (ret) - return -1; - - return 0; -} - -/* - * This function constructs a scan command configuration structure to use - * in scan commands. - * - * Application layer or other functions can invoke network scanning - * with a scan configuration supplied in a user scan configuration structure. - * This structure is used as the basis of one or many scan command configuration - * commands that are sent to the command processing module and eventually to the - * firmware. - * - * This function creates a scan command configuration structure based on the - * following user supplied parameters (if present): - * - SSID filter - * - BSSID filter - * - Number of Probes to be sent - * - Channel list - * - * If the SSID or BSSID filter is not present, the filter is disabled/cleared. - * If the number of probes is not set, adapter default setting is used. - */ -static void -mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg *user_scan_in, - struct mwifiex_scan_cmd_config *scan_cfg_out, - struct mwifiex_ie_types_chan_list_param_set - **chan_list_out, - struct mwifiex_chan_scan_param_set - *scan_chan_list, - u8 *max_chan_per_scan, u8 *filtered_scan, - u8 *scan_current_only) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_num_probes *num_probes_tlv; - struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; - struct mwifiex_ie_types_rates_param_set *rates_tlv; - const u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - u8 *tlv_pos; - u32 num_probes; - u32 ssid_len; - u32 chan_idx; - u32 scan_type; - u16 scan_dur; - u8 channel; - u8 radio_type; - u32 ssid_idx; - u8 ssid_filter; - u8 rates[MWIFIEX_SUPPORTED_RATES]; - u32 rates_size; - struct mwifiex_ie_types_htcap *ht_cap; - - /* The tlv_buf_len is calculated for each scan command. The TLVs added - in this routine will be preserved since the routine that sends the - command will append channelTLVs at *chan_list_out. The difference - between the *chan_list_out and the tlv_buf start will be used to - calculate the size of anything we add in this routine. */ - scan_cfg_out->tlv_buf_len = 0; - - /* Running tlv pointer. Assigned to chan_list_out at end of function - so later routines know where channels can be added to the command - buf */ - tlv_pos = scan_cfg_out->tlv_buf; - - /* Initialize the scan as un-filtered; the flag is later set to TRUE - below if a SSID or BSSID filter is sent in the command */ - *filtered_scan = false; - - /* Initialize the scan as not being only on the current channel. If - the channel list is customized, only contains one channel, and is - the active channel, this is set true and data flow is not halted. */ - *scan_current_only = false; - - if (user_scan_in) { - - /* Default the ssid_filter flag to TRUE, set false under - certain wildcard conditions and qualified by the existence - of an SSID list before marking the scan as filtered */ - ssid_filter = true; - - /* Set the BSS type scan filter, use Adapter setting if - unset */ - scan_cfg_out->bss_mode = - (user_scan_in->bss_mode ? (u8) user_scan_in-> - bss_mode : (u8) adapter->scan_mode); - - /* Set the number of probes to send, use Adapter setting - if unset */ - num_probes = - (user_scan_in->num_probes ? user_scan_in-> - num_probes : adapter->scan_probes); - - /* - * Set the BSSID filter to the incoming configuration, - * if non-zero. If not set, it will remain disabled - * (all zeros). - */ - memcpy(scan_cfg_out->specific_bssid, - user_scan_in->specific_bssid, - sizeof(scan_cfg_out->specific_bssid)); - - for (ssid_idx = 0; - ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list)) - && (*user_scan_in->ssid_list[ssid_idx].ssid - || user_scan_in->ssid_list[ssid_idx].max_len)); - ssid_idx++) { - - ssid_len = strlen(user_scan_in->ssid_list[ssid_idx]. - ssid) + 1; - - wildcard_ssid_tlv = - (struct mwifiex_ie_types_wildcard_ssid_params *) - tlv_pos; - wildcard_ssid_tlv->header.type = - cpu_to_le16(TLV_TYPE_WILDCARDSSID); - wildcard_ssid_tlv->header.len = cpu_to_le16( - (u16) (ssid_len + sizeof(wildcard_ssid_tlv-> - max_ssid_length))); - wildcard_ssid_tlv->max_ssid_length = - user_scan_in->ssid_list[ssid_idx].max_len; - - memcpy(wildcard_ssid_tlv->ssid, - user_scan_in->ssid_list[ssid_idx].ssid, - ssid_len); - - tlv_pos += (sizeof(wildcard_ssid_tlv->header) - + le16_to_cpu(wildcard_ssid_tlv->header.len)); - - dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n", - ssid_idx, wildcard_ssid_tlv->ssid, - wildcard_ssid_tlv->max_ssid_length); - - /* Empty wildcard ssid with a maxlen will match many or - potentially all SSIDs (maxlen == 32), therefore do - not treat the scan as - filtered. */ - if (!ssid_len && wildcard_ssid_tlv->max_ssid_length) - ssid_filter = false; - - } - - /* - * The default number of channels sent in the command is low to - * ensure the response buffer from the firmware does not - * truncate scan results. That is not an issue with an SSID - * or BSSID filter applied to the scan results in the firmware. - */ - if ((ssid_idx && ssid_filter) - || memcmp(scan_cfg_out->specific_bssid, &zero_mac, - sizeof(zero_mac))) - *filtered_scan = true; - } else { - scan_cfg_out->bss_mode = (u8) adapter->scan_mode; - num_probes = adapter->scan_probes; - } - - /* - * If a specific BSSID or SSID is used, the number of channels in the - * scan command will be increased to the absolute maximum. - */ - if (*filtered_scan) - *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; - else - *max_chan_per_scan = MWIFIEX_CHANNELS_PER_SCAN_CMD; - - /* If the input config or adapter has the number of Probes set, - add tlv */ - if (num_probes) { - - dev_dbg(adapter->dev, "info: scan: num_probes = %d\n", - num_probes); - - num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos; - num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); - num_probes_tlv->header.len = - cpu_to_le16(sizeof(num_probes_tlv->num_probes)); - num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes); - - tlv_pos += sizeof(num_probes_tlv->header) + - le16_to_cpu(num_probes_tlv->header.len); - - } - - /* Append rates tlv */ - memset(rates, 0, sizeof(rates)); - - rates_size = mwifiex_get_supported_rates(priv, rates); - - rates_tlv = (struct mwifiex_ie_types_rates_param_set *) tlv_pos; - rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); - rates_tlv->header.len = cpu_to_le16((u16) rates_size); - memcpy(rates_tlv->rates, rates, rates_size); - tlv_pos += sizeof(rates_tlv->header) + rates_size; - - dev_dbg(adapter->dev, "info: SCAN_CMD: Rates size = %d\n", rates_size); - - if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) - && (priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN)) { - ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos; - memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); - ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - radio_type = - mwifiex_band_to_radio_type(priv->adapter->config_bands); - mwifiex_fill_cap_info(priv, radio_type, ht_cap); - tlv_pos += sizeof(struct mwifiex_ie_types_htcap); - } - - /* Append vendor specific IE TLV */ - mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos); - - /* - * Set the output for the channel TLV to the address in the tlv buffer - * past any TLVs that were added in this function (SSID, num_probes). - * Channel TLVs will be added past this for each scan command, - * preserving the TLVs that were previously added. - */ - *chan_list_out = - (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos; - - if (user_scan_in && user_scan_in->chan_list[0].chan_number) { - - dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n"); - - for (chan_idx = 0; - chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX - && user_scan_in->chan_list[chan_idx].chan_number; - chan_idx++) { - - channel = user_scan_in->chan_list[chan_idx].chan_number; - (scan_chan_list + chan_idx)->chan_number = channel; - - radio_type = - user_scan_in->chan_list[chan_idx].radio_type; - (scan_chan_list + chan_idx)->radio_type = radio_type; - - scan_type = user_scan_in->chan_list[chan_idx].scan_type; - - if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap - |= MWIFIEX_PASSIVE_SCAN; - else - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap - &= ~MWIFIEX_PASSIVE_SCAN; - - if (user_scan_in->chan_list[chan_idx].scan_time) { - scan_dur = (u16) user_scan_in-> - chan_list[chan_idx].scan_time; - } else { - if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - scan_dur = adapter->passive_scan_time; - else if (*filtered_scan) - scan_dur = adapter->specific_scan_time; - else - scan_dur = adapter->active_scan_time; - } - - (scan_chan_list + chan_idx)->min_scan_time = - cpu_to_le16(scan_dur); - (scan_chan_list + chan_idx)->max_scan_time = - cpu_to_le16(scan_dur); - } - - /* Check if we are only scanning the current channel */ - if ((chan_idx == 1) - && (user_scan_in->chan_list[0].chan_number - == priv->curr_bss_params.bss_descriptor.channel)) { - *scan_current_only = true; - dev_dbg(adapter->dev, - "info: Scan: Scanning current channel only\n"); - } - - } else { - dev_dbg(adapter->dev, - "info: Scan: Creating full region channel list\n"); - mwifiex_scan_create_channel_list(priv, user_scan_in, - scan_chan_list, - *filtered_scan); - } -} - -/* - * This function inspects the scan response buffer for pointers to - * expected TLVs. - * - * TLVs can be included at the end of the scan response BSS information. - * - * Data in the buffer is parsed pointers to TLVs that can potentially - * be passed back in the response. - */ -static void -mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, - struct mwifiex_ie_types_data *tlv, - u32 tlv_buf_size, u32 req_tlv_type, - struct mwifiex_ie_types_data **tlv_data) -{ - struct mwifiex_ie_types_data *current_tlv; - u32 tlv_buf_left; - u32 tlv_type; - u32 tlv_len; - - current_tlv = tlv; - tlv_buf_left = tlv_buf_size; - *tlv_data = NULL; - - dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n", - tlv_buf_size); - - while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) { - - tlv_type = le16_to_cpu(current_tlv->header.type); - tlv_len = le16_to_cpu(current_tlv->header.len); - - if (sizeof(tlv->header) + tlv_len > tlv_buf_left) { - dev_err(adapter->dev, "SCAN_RESP: TLV buffer corrupt\n"); - break; - } - - if (req_tlv_type == tlv_type) { - switch (tlv_type) { - case TLV_TYPE_TSFTIMESTAMP: - dev_dbg(adapter->dev, "info: SCAN_RESP: TSF " - "timestamp TLV, len = %d\n", tlv_len); - *tlv_data = (struct mwifiex_ie_types_data *) - current_tlv; - break; - case TLV_TYPE_CHANNELBANDLIST: - dev_dbg(adapter->dev, "info: SCAN_RESP: channel" - " band list TLV, len = %d\n", tlv_len); - *tlv_data = (struct mwifiex_ie_types_data *) - current_tlv; - break; - default: - dev_err(adapter->dev, - "SCAN_RESP: unhandled TLV = %d\n", - tlv_type); - /* Give up, this seems corrupted */ - return; - } - } - - if (*tlv_data) - break; - - - tlv_buf_left -= (sizeof(tlv->header) + tlv_len); - current_tlv = - (struct mwifiex_ie_types_data *) (current_tlv->data + - tlv_len); - - } /* while */ -} - -/* - * This function interprets a BSS scan response returned from the firmware. - * - * The various fixed fields and IEs are parsed and passed back for a BSS - * probe response or beacon from scan command. Information is recorded as - * needed in the scan table for that entry. - * - * The following IE types are recognized and parsed - - * - SSID - * - Supported rates - * - FH parameters set - * - DS parameters set - * - CF parameters set - * - IBSS parameters set - * - ERP information - * - Extended supported rates - * - Vendor specific (221) - * - RSN IE - * - WAPI IE - * - HT capability - * - HT operation - * - BSS Coexistence 20/40 - * - Extended capability - * - Overlapping BSS scan parameters - */ -static int -mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, - struct mwifiex_bssdescriptor *bss_entry, - u8 **beacon_info, u32 *bytes_left) -{ - int ret = 0; - u8 element_id; - struct ieee_types_fh_param_set *fh_param_set; - struct ieee_types_ds_param_set *ds_param_set; - struct ieee_types_cf_param_set *cf_param_set; - struct ieee_types_ibss_param_set *ibss_param_set; - __le16 beacon_interval; - __le16 capabilities; - u8 *current_ptr; - u8 *rate; - u8 element_len; - u16 total_ie_len; - u8 bytes_to_copy; - u8 rate_size; - u16 beacon_size; - u8 found_data_rate_ie; - u32 bytes_left_for_current_beacon; - struct ieee_types_vendor_specific *vendor_ie; - const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; - const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; - - found_data_rate_ie = false; - rate_size = 0; - beacon_size = 0; - - if (*bytes_left >= sizeof(beacon_size)) { - /* Extract & convert beacon size from the command buffer */ - memcpy(&beacon_size, *beacon_info, sizeof(beacon_size)); - *bytes_left -= sizeof(beacon_size); - *beacon_info += sizeof(beacon_size); - } - - if (!beacon_size || beacon_size > *bytes_left) { - *beacon_info += *bytes_left; - *bytes_left = 0; - return -1; - } - - /* Initialize the current working beacon pointer for this BSS - iteration */ - current_ptr = *beacon_info; - - /* Advance the return beacon pointer past the current beacon */ - *beacon_info += beacon_size; - *bytes_left -= beacon_size; - - bytes_left_for_current_beacon = beacon_size; - - memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN); - dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n", - bss_entry->mac_address); - - current_ptr += ETH_ALEN; - bytes_left_for_current_beacon -= ETH_ALEN; - - if (bytes_left_for_current_beacon < 12) { - dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); - return -1; - } - - /* - * Next 4 fields are RSSI, time stamp, beacon interval, - * and capability information - */ - - /* RSSI is 1 byte long */ - bss_entry->rssi = (s32) (*current_ptr); - dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr); - current_ptr += 1; - bytes_left_for_current_beacon -= 1; - - /* - * The RSSI is not part of the beacon/probe response. After we have - * advanced current_ptr past the RSSI field, save the remaining - * data for use at the application layer - */ - bss_entry->beacon_buf = current_ptr; - bss_entry->beacon_buf_size = bytes_left_for_current_beacon; - - /* Time stamp is 8 bytes long */ - memcpy(bss_entry->time_stamp, current_ptr, 8); - current_ptr += 8; - bytes_left_for_current_beacon -= 8; - - /* Beacon interval is 2 bytes long */ - memcpy(&beacon_interval, current_ptr, 2); - bss_entry->beacon_period = le16_to_cpu(beacon_interval); - current_ptr += 2; - bytes_left_for_current_beacon -= 2; - - /* Capability information is 2 bytes long */ - memcpy(&capabilities, current_ptr, 2); - dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", - capabilities); - bss_entry->cap_info_bitmap = le16_to_cpu(capabilities); - current_ptr += 2; - bytes_left_for_current_beacon -= 2; - - /* Rest of the current buffer are IE's */ - dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n", - bytes_left_for_current_beacon); - - if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { - dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n"); - bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; - } else { - bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; - } - - if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS) - bss_entry->bss_mode = NL80211_IFTYPE_ADHOC; - else - bss_entry->bss_mode = NL80211_IFTYPE_STATION; - - - /* Process variable IE */ - while (bytes_left_for_current_beacon >= 2) { - element_id = *current_ptr; - element_len = *(current_ptr + 1); - total_ie_len = element_len + sizeof(struct ieee_types_header); - - if (bytes_left_for_current_beacon < total_ie_len) { - dev_err(adapter->dev, "err: InterpretIE: in processing" - " IE, bytes left < IE length\n"); - bytes_left_for_current_beacon = 0; - ret = -1; - continue; - } - switch (element_id) { - case WLAN_EID_SSID: - bss_entry->ssid.ssid_len = element_len; - memcpy(bss_entry->ssid.ssid, (current_ptr + 2), - element_len); - dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n", - bss_entry->ssid.ssid); - break; - - case WLAN_EID_SUPP_RATES: - memcpy(bss_entry->data_rates, current_ptr + 2, - element_len); - memcpy(bss_entry->supported_rates, current_ptr + 2, - element_len); - rate_size = element_len; - found_data_rate_ie = true; - break; - - case WLAN_EID_FH_PARAMS: - fh_param_set = - (struct ieee_types_fh_param_set *) current_ptr; - memcpy(&bss_entry->phy_param_set.fh_param_set, - fh_param_set, - sizeof(struct ieee_types_fh_param_set)); - break; - - case WLAN_EID_DS_PARAMS: - ds_param_set = - (struct ieee_types_ds_param_set *) current_ptr; - - bss_entry->channel = ds_param_set->current_chan; - - memcpy(&bss_entry->phy_param_set.ds_param_set, - ds_param_set, - sizeof(struct ieee_types_ds_param_set)); - break; - - case WLAN_EID_CF_PARAMS: - cf_param_set = - (struct ieee_types_cf_param_set *) current_ptr; - memcpy(&bss_entry->ss_param_set.cf_param_set, - cf_param_set, - sizeof(struct ieee_types_cf_param_set)); - break; - - case WLAN_EID_IBSS_PARAMS: - ibss_param_set = - (struct ieee_types_ibss_param_set *) - current_ptr; - memcpy(&bss_entry->ss_param_set.ibss_param_set, - ibss_param_set, - sizeof(struct ieee_types_ibss_param_set)); - break; - - case WLAN_EID_ERP_INFO: - bss_entry->erp_flags = *(current_ptr + 2); - break; - - case WLAN_EID_EXT_SUPP_RATES: - /* - * Only process extended supported rate - * if data rate is already found. - * Data rate IE should come before - * extended supported rate IE - */ - if (found_data_rate_ie) { - if ((element_len + rate_size) > - MWIFIEX_SUPPORTED_RATES) - bytes_to_copy = - (MWIFIEX_SUPPORTED_RATES - - rate_size); - else - bytes_to_copy = element_len; - - rate = (u8 *) bss_entry->data_rates; - rate += rate_size; - memcpy(rate, current_ptr + 2, bytes_to_copy); - - rate = (u8 *) bss_entry->supported_rates; - rate += rate_size; - memcpy(rate, current_ptr + 2, bytes_to_copy); - } - break; - - case WLAN_EID_VENDOR_SPECIFIC: - vendor_ie = (struct ieee_types_vendor_specific *) - current_ptr; - - if (!memcmp - (vendor_ie->vend_hdr.oui, wpa_oui, - sizeof(wpa_oui))) { - bss_entry->bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - current_ptr; - bss_entry->wpa_offset = (u16) (current_ptr - - bss_entry->beacon_buf); - } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, - sizeof(wmm_oui))) { - if (total_ie_len == - sizeof(struct ieee_types_wmm_parameter) - || total_ie_len == - sizeof(struct ieee_types_wmm_info)) - /* - * Only accept and copy the WMM IE if - * it matches the size expected for the - * WMM Info IE or the WMM Parameter IE. - */ - memcpy((u8 *) &bss_entry->wmm_ie, - current_ptr, total_ie_len); - } - break; - case WLAN_EID_RSN: - bss_entry->bcn_rsn_ie = - (struct ieee_types_generic *) current_ptr; - bss_entry->rsn_offset = (u16) (current_ptr - - bss_entry->beacon_buf); - break; - case WLAN_EID_BSS_AC_ACCESS_DELAY: - bss_entry->bcn_wapi_ie = - (struct ieee_types_generic *) current_ptr; - bss_entry->wapi_offset = (u16) (current_ptr - - bss_entry->beacon_buf); - break; - case WLAN_EID_HT_CAPABILITY: - bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *) - (current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->ht_cap_offset = (u16) (current_ptr + - sizeof(struct ieee_types_header) - - bss_entry->beacon_buf); - break; - case WLAN_EID_HT_INFORMATION: - bss_entry->bcn_ht_info = (struct ieee80211_ht_info *) - (current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->ht_info_offset = (u16) (current_ptr + - sizeof(struct ieee_types_header) - - bss_entry->beacon_buf); - break; - case WLAN_EID_BSS_COEX_2040: - bss_entry->bcn_bss_co_2040 = (u8 *) (current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->bss_co_2040_offset = (u16) (current_ptr + - sizeof(struct ieee_types_header) - - bss_entry->beacon_buf); - break; - case WLAN_EID_EXT_CAPABILITY: - bss_entry->bcn_ext_cap = (u8 *) (current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->ext_cap_offset = (u16) (current_ptr + - sizeof(struct ieee_types_header) - - bss_entry->beacon_buf); - break; - case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: - bss_entry->bcn_obss_scan = - (struct ieee_types_obss_scan_param *) - current_ptr; - bss_entry->overlap_bss_offset = (u16) (current_ptr - - bss_entry->beacon_buf); - break; - default: - break; - } - - current_ptr += element_len + 2; - - /* Need to account for IE ID and IE Len */ - bytes_left_for_current_beacon -= (element_len + 2); - - } /* while (bytes_left_for_current_beacon > 2) */ - return ret; -} - -/* - * This function adjusts the pointers used in beacon buffers to reflect - * shifts. - * - * The memory allocated for beacon buffers is of fixed sizes where all the - * saved beacons must be stored. New beacons are added in the free portion - * of this memory, space permitting; while duplicate beacon buffers are - * placed at the same start location. However, since duplicate beacon - * buffers may not match the size of the old one, all the following buffers - * in the memory must be shifted to either make space, or to fill up freed - * up space. - * - * This function is used to update the beacon buffer pointers that are past - * an existing beacon buffer that is updated with a new one of different - * size. The pointers are shifted by a fixed amount, either forward or - * backward. - * - * the following pointers in every affected beacon buffers are changed, if - * present - - * - WPA IE pointer - * - RSN IE pointer - * - WAPI IE pointer - * - HT capability IE pointer - * - HT information IE pointer - * - BSS coexistence 20/40 IE pointer - * - Extended capability IE pointer - * - Overlapping BSS scan parameter IE pointer - */ -static void -mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance, - u8 *bcn_store, u32 rem_bcn_size, - u32 num_of_ent) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u32 adj_idx; - for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) { - if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) { - - if (advance) - adapter->scan_table[adj_idx].beacon_buf += - rem_bcn_size; - else - adapter->scan_table[adj_idx].beacon_buf -= - rem_bcn_size; - - if (adapter->scan_table[adj_idx].bcn_wpa_ie) - adapter->scan_table[adj_idx].bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].wpa_offset); - if (adapter->scan_table[adj_idx].bcn_rsn_ie) - adapter->scan_table[adj_idx].bcn_rsn_ie = - (struct ieee_types_generic *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].rsn_offset); - if (adapter->scan_table[adj_idx].bcn_wapi_ie) - adapter->scan_table[adj_idx].bcn_wapi_ie = - (struct ieee_types_generic *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].wapi_offset); - if (adapter->scan_table[adj_idx].bcn_ht_cap) - adapter->scan_table[adj_idx].bcn_ht_cap = - (struct ieee80211_ht_cap *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].ht_cap_offset); - - if (adapter->scan_table[adj_idx].bcn_ht_info) - adapter->scan_table[adj_idx].bcn_ht_info = - (struct ieee80211_ht_info *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].ht_info_offset); - if (adapter->scan_table[adj_idx].bcn_bss_co_2040) - adapter->scan_table[adj_idx].bcn_bss_co_2040 = - (u8 *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].bss_co_2040_offset); - if (adapter->scan_table[adj_idx].bcn_ext_cap) - adapter->scan_table[adj_idx].bcn_ext_cap = - (u8 *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].ext_cap_offset); - if (adapter->scan_table[adj_idx].bcn_obss_scan) - adapter->scan_table[adj_idx].bcn_obss_scan = - (struct ieee_types_obss_scan_param *) - (adapter->scan_table[adj_idx].beacon_buf + - adapter->scan_table[adj_idx].overlap_bss_offset); - } - } -} - -/* - * This function updates the pointers used in beacon buffer for given bss - * descriptor to reflect shifts - * - * Following pointers are updated - * - WPA IE pointer - * - RSN IE pointer - * - WAPI IE pointer - * - HT capability IE pointer - * - HT information IE pointer - * - BSS coexistence 20/40 IE pointer - * - Extended capability IE pointer - * - Overlapping BSS scan parameter IE pointer - */ -static void -mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon) -{ - if (beacon->bcn_wpa_ie) - beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *) - (beacon->beacon_buf + beacon->wpa_offset); - if (beacon->bcn_rsn_ie) - beacon->bcn_rsn_ie = (struct ieee_types_generic *) - (beacon->beacon_buf + beacon->rsn_offset); - if (beacon->bcn_wapi_ie) - beacon->bcn_wapi_ie = (struct ieee_types_generic *) - (beacon->beacon_buf + beacon->wapi_offset); - if (beacon->bcn_ht_cap) - beacon->bcn_ht_cap = (struct ieee80211_ht_cap *) - (beacon->beacon_buf + beacon->ht_cap_offset); - if (beacon->bcn_ht_info) - beacon->bcn_ht_info = (struct ieee80211_ht_info *) - (beacon->beacon_buf + beacon->ht_info_offset); - if (beacon->bcn_bss_co_2040) - beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf + - beacon->bss_co_2040_offset); - if (beacon->bcn_ext_cap) - beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf + - beacon->ext_cap_offset); - if (beacon->bcn_obss_scan) - beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *) - (beacon->beacon_buf + beacon->overlap_bss_offset); -} - -/* - * This function stores a beacon or probe response for a BSS returned - * in the scan. - * - * This stores a new scan response or an update for a previous scan response. - * New entries need to verify that they do not exceed the total amount of - * memory allocated for the table. - * - * Replacement entries need to take into consideration the amount of space - * currently allocated for the beacon/probe response and adjust the entry - * as needed. - * - * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved - * for an entry in case it is a beacon since a probe response for the - * network will by larger per the standard. This helps to reduce the - * amount of memory copying to fit a new probe response into an entry - * already occupied by a network's previously stored beacon. - */ -static void -mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv, - u32 beacon_idx, u32 num_of_ent, - struct mwifiex_bssdescriptor *new_beacon) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 *bcn_store; - u32 new_bcn_size; - u32 old_bcn_size; - u32 bcn_space; - - if (adapter->scan_table[beacon_idx].beacon_buf) { - - new_bcn_size = new_beacon->beacon_buf_size; - old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size; - bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max; - bcn_store = adapter->scan_table[beacon_idx].beacon_buf; - - /* Set the max to be the same as current entry unless changed - below */ - new_beacon->beacon_buf_size_max = bcn_space; - if (new_bcn_size == old_bcn_size) { - /* - * Beacon is the same size as the previous entry. - * Replace the previous contents with the scan result - */ - memcpy(bcn_store, new_beacon->beacon_buf, - new_beacon->beacon_buf_size); - - } else if (new_bcn_size <= bcn_space) { - /* - * New beacon size will fit in the amount of space - * we have previously allocated for it - */ - - /* Copy the new beacon buffer entry over the old one */ - memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); - - /* - * If the old beacon size was less than the maximum - * we had alloted for the entry, and the new entry - * is even smaller, reset the max size to the old - * beacon entry and compress the storage space - * (leaving a new pad space of (old_bcn_size - - * new_bcn_size). - */ - if (old_bcn_size < bcn_space - && new_bcn_size <= old_bcn_size) { - /* - * Old Beacon size is smaller than the alloted - * storage size. Shrink the alloted storage - * space. - */ - dev_dbg(adapter->dev, "info: AppControl:" - " smaller duplicate beacon " - "(%d), old = %d, new = %d, space = %d," - "left = %d\n", - beacon_idx, old_bcn_size, new_bcn_size, - bcn_space, - (int)(sizeof(adapter->bcn_buf) - - (adapter->bcn_buf_end - - adapter->bcn_buf))); - - /* - * memmove (since the memory overlaps) the - * data after the beacon we just stored to the - * end of the current beacon. This cleans up - * any unused space the old larger beacon was - * using in the buffer - */ - memmove(bcn_store + old_bcn_size, - bcn_store + bcn_space, - adapter->bcn_buf_end - (bcn_store + - bcn_space)); - - /* - * Decrement the end pointer by the difference - * between the old larger size and the new - * smaller size since we are using less space - * due to the new beacon being smaller - */ - adapter->bcn_buf_end -= - (bcn_space - old_bcn_size); - - /* Set the maximum storage size to the old - beacon size */ - new_beacon->beacon_buf_size_max = old_bcn_size; - - /* Adjust beacon buffer pointers that are past - the current */ - mwifiex_adjust_beacon_buffer_ptrs(priv, 0, - bcn_store, (bcn_space - old_bcn_size), - num_of_ent); - } - } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space) - < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) { - /* - * Beacon is larger than space previously allocated - * (bcn_space) and there is enough space left in the - * beaconBuffer to store the additional data - */ - dev_dbg(adapter->dev, "info: AppControl:" - " larger duplicate beacon (%d), " - "old = %d, new = %d, space = %d, left = %d\n", - beacon_idx, old_bcn_size, new_bcn_size, - bcn_space, - (int)(sizeof(adapter->bcn_buf) - - (adapter->bcn_buf_end - - adapter->bcn_buf))); - - /* - * memmove (since the memory overlaps) the data - * after the beacon we just stored to the end of - * the current beacon. This moves the data for - * the beacons after this further in memory to - * make space for the new larger beacon we are - * about to copy in. - */ - memmove(bcn_store + new_bcn_size, - bcn_store + bcn_space, - adapter->bcn_buf_end - (bcn_store + bcn_space)); - - /* Copy the new beacon buffer entry over the old one */ - memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); - - /* Move the beacon end pointer by the amount of new - beacon data we are adding */ - adapter->bcn_buf_end += (new_bcn_size - bcn_space); - - /* - * This entry is bigger than the alloted max space - * previously reserved. Increase the max space to - * be equal to the new beacon size - */ - new_beacon->beacon_buf_size_max = new_bcn_size; - - /* Adjust beacon buffer pointers that are past the - current */ - mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store, - (new_bcn_size - bcn_space), - num_of_ent); - } else { - /* - * Beacon is larger than the previously allocated space, - * but there is not enough free space to store the - * additional data. - */ - dev_err(adapter->dev, "AppControl: larger duplicate " - " beacon (%d), old = %d new = %d, space = %d," - " left = %d\n", beacon_idx, old_bcn_size, - new_bcn_size, bcn_space, - (int)(sizeof(adapter->bcn_buf) - - (adapter->bcn_buf_end - adapter->bcn_buf))); - - /* Storage failure, keep old beacon intact */ - new_beacon->beacon_buf_size = old_bcn_size; - if (new_beacon->bcn_wpa_ie) - new_beacon->wpa_offset = - adapter->scan_table[beacon_idx]. - wpa_offset; - if (new_beacon->bcn_rsn_ie) - new_beacon->rsn_offset = - adapter->scan_table[beacon_idx]. - rsn_offset; - if (new_beacon->bcn_wapi_ie) - new_beacon->wapi_offset = - adapter->scan_table[beacon_idx]. - wapi_offset; - if (new_beacon->bcn_ht_cap) - new_beacon->ht_cap_offset = - adapter->scan_table[beacon_idx]. - ht_cap_offset; - if (new_beacon->bcn_ht_info) - new_beacon->ht_info_offset = - adapter->scan_table[beacon_idx]. - ht_info_offset; - if (new_beacon->bcn_bss_co_2040) - new_beacon->bss_co_2040_offset = - adapter->scan_table[beacon_idx]. - bss_co_2040_offset; - if (new_beacon->bcn_ext_cap) - new_beacon->ext_cap_offset = - adapter->scan_table[beacon_idx]. - ext_cap_offset; - if (new_beacon->bcn_obss_scan) - new_beacon->overlap_bss_offset = - adapter->scan_table[beacon_idx]. - overlap_bss_offset; - } - /* Point the new entry to its permanent storage space */ - new_beacon->beacon_buf = bcn_store; - mwifiex_update_beacon_buffer_ptrs(new_beacon); - } else { - /* - * No existing beacon data exists for this entry, check to see - * if we can fit it in the remaining space - */ - if (adapter->bcn_buf_end + new_beacon->beacon_buf_size + - SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf + - sizeof(adapter->bcn_buf))) { - - /* - * Copy the beacon buffer data from the local entry to - * the adapter dev struct buffer space used to store - * the raw beacon data for each entry in the scan table - */ - memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf, - new_beacon->beacon_buf_size); - - /* Update the beacon ptr to point to the table save - area */ - new_beacon->beacon_buf = adapter->bcn_buf_end; - new_beacon->beacon_buf_size_max = - (new_beacon->beacon_buf_size + - SCAN_BEACON_ENTRY_PAD); - - mwifiex_update_beacon_buffer_ptrs(new_beacon); - - /* Increment the end pointer by the size reserved */ - adapter->bcn_buf_end += new_beacon->beacon_buf_size_max; - - dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]" - " sz=%03d, used = %04d, left = %04d\n", - beacon_idx, - new_beacon->beacon_buf_size, - (int)(adapter->bcn_buf_end - adapter->bcn_buf), - (int)(sizeof(adapter->bcn_buf) - - (adapter->bcn_buf_end - - adapter->bcn_buf))); - } else { - /* No space for new beacon */ - dev_dbg(adapter->dev, "info: AppControl: no space for" - " beacon (%d): %pM sz=%03d, left=%03d\n", - beacon_idx, new_beacon->mac_address, - new_beacon->beacon_buf_size, - (int)(sizeof(adapter->bcn_buf) - - (adapter->bcn_buf_end - - adapter->bcn_buf))); - - /* Storage failure; clear storage records for this - bcn */ - new_beacon->beacon_buf = NULL; - new_beacon->beacon_buf_size = 0; - new_beacon->beacon_buf_size_max = 0; - new_beacon->bcn_wpa_ie = NULL; - new_beacon->wpa_offset = 0; - new_beacon->bcn_rsn_ie = NULL; - new_beacon->rsn_offset = 0; - new_beacon->bcn_wapi_ie = NULL; - new_beacon->wapi_offset = 0; - new_beacon->bcn_ht_cap = NULL; - new_beacon->ht_cap_offset = 0; - new_beacon->bcn_ht_info = NULL; - new_beacon->ht_info_offset = 0; - new_beacon->bcn_bss_co_2040 = NULL; - new_beacon->bss_co_2040_offset = 0; - new_beacon->bcn_ext_cap = NULL; - new_beacon->ext_cap_offset = 0; - new_beacon->bcn_obss_scan = NULL; - new_beacon->overlap_bss_offset = 0; - } - } -} - -/* - * This function restores a beacon buffer of the current BSS descriptor. - */ -static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *curr_bss = - &priv->curr_bss_params.bss_descriptor; - unsigned long flags; - - if (priv->curr_bcn_buf && - ((adapter->bcn_buf_end + priv->curr_bcn_size) < - (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) { - spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); - - /* restore the current beacon buffer */ - memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf, - priv->curr_bcn_size); - curr_bss->beacon_buf = adapter->bcn_buf_end; - curr_bss->beacon_buf_size = priv->curr_bcn_size; - adapter->bcn_buf_end += priv->curr_bcn_size; - - /* adjust the pointers in the current BSS descriptor */ - if (curr_bss->bcn_wpa_ie) - curr_bss->bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - (curr_bss->beacon_buf + - curr_bss->wpa_offset); - - if (curr_bss->bcn_rsn_ie) - curr_bss->bcn_rsn_ie = (struct ieee_types_generic *) - (curr_bss->beacon_buf + - curr_bss->rsn_offset); - - if (curr_bss->bcn_ht_cap) - curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *) - (curr_bss->beacon_buf + - curr_bss->ht_cap_offset); - - if (curr_bss->bcn_ht_info) - curr_bss->bcn_ht_info = (struct ieee80211_ht_info *) - (curr_bss->beacon_buf + - curr_bss->ht_info_offset); - - if (curr_bss->bcn_bss_co_2040) - curr_bss->bcn_bss_co_2040 = - (u8 *) (curr_bss->beacon_buf + - curr_bss->bss_co_2040_offset); - - if (curr_bss->bcn_ext_cap) - curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf + - curr_bss->ext_cap_offset); - - if (curr_bss->bcn_obss_scan) - curr_bss->bcn_obss_scan = - (struct ieee_types_obss_scan_param *) - (curr_bss->beacon_buf + - curr_bss->overlap_bss_offset); - - spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); - - dev_dbg(adapter->dev, "info: current beacon restored %d\n", - priv->curr_bcn_size); - } else { - dev_warn(adapter->dev, - "curr_bcn_buf not saved or bcn_buf has no space\n"); - } -} - -/* - * This function post processes the scan table after a new scan command has - * completed. - * - * It inspects each entry of the scan table and tries to find an entry that - * matches with our current associated/joined network from the scan. If - * one is found, the stored copy of the BSS descriptor of our current network - * is updated. - * - * It also debug dumps the current scan table contents after processing is over. - */ -static void -mwifiex_process_scan_results(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - s32 j; - u32 i; - unsigned long flags; - - if (priv->media_connected) { - - j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params. - bss_descriptor.ssid, - priv->curr_bss_params. - bss_descriptor.mac_address, - priv->bss_mode); - - if (j >= 0) { - spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); - priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL; - priv->curr_bss_params.bss_descriptor.wpa_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL; - priv->curr_bss_params.bss_descriptor.rsn_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; - priv->curr_bss_params.bss_descriptor.wapi_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; - priv->curr_bss_params.bss_descriptor.ht_cap_offset = - 0; - priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL; - priv->curr_bss_params.bss_descriptor.ht_info_offset = - 0; - priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = - NULL; - priv->curr_bss_params.bss_descriptor. - bss_co_2040_offset = 0; - priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; - priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; - priv->curr_bss_params.bss_descriptor. - bcn_obss_scan = NULL; - priv->curr_bss_params.bss_descriptor. - overlap_bss_offset = 0; - priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; - priv->curr_bss_params.bss_descriptor.beacon_buf_size = - 0; - priv->curr_bss_params.bss_descriptor. - beacon_buf_size_max = 0; - - dev_dbg(adapter->dev, "info: Found current ssid/bssid" - " in list @ index #%d\n", j); - /* Make a copy of current BSSID descriptor */ - memcpy(&priv->curr_bss_params.bss_descriptor, - &adapter->scan_table[j], - sizeof(priv->curr_bss_params.bss_descriptor)); - - mwifiex_save_curr_bcn(priv); - spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); - - } else { - mwifiex_restore_curr_bcn(priv); - } - } - - for (i = 0; i < adapter->num_in_scan_table; i++) - dev_dbg(adapter->dev, "info: scan:(%02d) %pM " - "RSSI[%03d], SSID[%s]\n", - i, adapter->scan_table[i].mac_address, - (s32) adapter->scan_table[i].rssi, - adapter->scan_table[i].ssid.ssid); -} - -/* - * This function converts radio type scan parameter to a band configuration - * to be used in join command. - */ -static u8 -mwifiex_radio_type_to_band(u8 radio_type) -{ - switch (radio_type) { - case HostCmd_SCAN_RADIO_TYPE_A: - return BAND_A; - case HostCmd_SCAN_RADIO_TYPE_BG: - default: - return BAND_G; - } -} - -/* - * This function deletes a specific indexed entry from the scan table. - * - * This also compacts the remaining entries and adjusts any buffering - * of beacon/probe response data if needed. - */ -static void -mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u32 del_idx; - u32 beacon_buf_adj; - u8 *beacon_buf; - - /* - * Shift the saved beacon buffer data for the scan table back over the - * entry being removed. Update the end of buffer pointer. Save the - * deleted buffer allocation size for pointer adjustments for entries - * compacted after the deleted index. - */ - beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max; - - dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer " - "removal = %d bytes\n", table_idx, beacon_buf_adj); - - /* Check if the table entry had storage allocated for its beacon */ - if (beacon_buf_adj) { - beacon_buf = adapter->scan_table[table_idx].beacon_buf; - - /* - * Remove the entry's buffer space, decrement the table end - * pointer by the amount we are removing - */ - adapter->bcn_buf_end -= beacon_buf_adj; - - dev_dbg(adapter->dev, "info: scan: delete entry %d," - " compact data: %p <- %p (sz = %d)\n", - table_idx, beacon_buf, - beacon_buf + beacon_buf_adj, - (int)(adapter->bcn_buf_end - beacon_buf)); - - /* - * Compact data storage. Copy all data after the deleted - * entry's end address (beacon_buf + beacon_buf_adj) back - * to the original start address (beacon_buf). - * - * Scan table entries affected by the move will have their - * entry pointer adjusted below. - * - * Use memmove since the dest/src memory regions overlap. - */ - memmove(beacon_buf, beacon_buf + beacon_buf_adj, - adapter->bcn_buf_end - beacon_buf); - } - - dev_dbg(adapter->dev, - "info: Scan: Delete Entry %d, num_in_scan_table = %d\n", - table_idx, adapter->num_in_scan_table); - - /* Shift all of the entries after the table_idx back by one, compacting - the table and removing the requested entry */ - for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table; - del_idx++) { - /* Copy the next entry over this one */ - memcpy(adapter->scan_table + del_idx, - adapter->scan_table + del_idx + 1, - sizeof(struct mwifiex_bssdescriptor)); - - /* - * Adjust this entry's pointer to its beacon buffer based on - * the removed/compacted entry from the deleted index. Don't - * decrement if the buffer pointer is NULL (no data stored for - * this entry). - */ - if (adapter->scan_table[del_idx].beacon_buf) { - adapter->scan_table[del_idx].beacon_buf -= - beacon_buf_adj; - if (adapter->scan_table[del_idx].bcn_wpa_ie) - adapter->scan_table[del_idx].bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - (adapter->scan_table[del_idx]. - beacon_buf + - adapter->scan_table[del_idx]. - wpa_offset); - if (adapter->scan_table[del_idx].bcn_rsn_ie) - adapter->scan_table[del_idx].bcn_rsn_ie = - (struct ieee_types_generic *) - (adapter->scan_table[del_idx]. - beacon_buf + - adapter->scan_table[del_idx]. - rsn_offset); - if (adapter->scan_table[del_idx].bcn_wapi_ie) - adapter->scan_table[del_idx].bcn_wapi_ie = - (struct ieee_types_generic *) - (adapter->scan_table[del_idx].beacon_buf - + adapter->scan_table[del_idx]. - wapi_offset); - if (adapter->scan_table[del_idx].bcn_ht_cap) - adapter->scan_table[del_idx].bcn_ht_cap = - (struct ieee80211_ht_cap *) - (adapter->scan_table[del_idx].beacon_buf - + adapter->scan_table[del_idx]. - ht_cap_offset); - - if (adapter->scan_table[del_idx].bcn_ht_info) - adapter->scan_table[del_idx].bcn_ht_info = - (struct ieee80211_ht_info *) - (adapter->scan_table[del_idx].beacon_buf - + adapter->scan_table[del_idx]. - ht_info_offset); - if (adapter->scan_table[del_idx].bcn_bss_co_2040) - adapter->scan_table[del_idx].bcn_bss_co_2040 = - (u8 *) - (adapter->scan_table[del_idx].beacon_buf - + adapter->scan_table[del_idx]. - bss_co_2040_offset); - if (adapter->scan_table[del_idx].bcn_ext_cap) - adapter->scan_table[del_idx].bcn_ext_cap = - (u8 *) - (adapter->scan_table[del_idx].beacon_buf - + adapter->scan_table[del_idx]. - ext_cap_offset); - if (adapter->scan_table[del_idx].bcn_obss_scan) - adapter->scan_table[del_idx]. - bcn_obss_scan = - (struct ieee_types_obss_scan_param *) - (adapter->scan_table[del_idx].beacon_buf - + adapter->scan_table[del_idx]. - overlap_bss_offset); - } - } - - /* The last entry is invalid now that it has been deleted or moved - back */ - memset(adapter->scan_table + adapter->num_in_scan_table - 1, - 0x00, sizeof(struct mwifiex_bssdescriptor)); - - adapter->num_in_scan_table--; -} - -/* - * This function deletes all occurrences of a given SSID from the scan table. - * - * This iterates through the scan table and deletes all entries that match - * the given SSID. It also compacts the remaining scan table entries. - */ -static int -mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *del_ssid) -{ - s32 table_idx = -1; - - dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n", - del_ssid->ssid); - - /* If the requested SSID is found in the table, delete it. Then keep - searching the table for multiple entires for the SSID until no - more are found */ - while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL, - NL80211_IFTYPE_UNSPECIFIED)) >= 0) { - dev_dbg(priv->adapter->dev, - "info: Scan: Delete SSID Entry: Found Idx = %d\n", - table_idx); - mwifiex_scan_delete_table_entry(priv, table_idx); - } - - return table_idx == -1 ? -1 : 0; -} - -/* - * This is an internal function used to start a scan based on an input - * configuration. - * - * This uses the input user scan configuration information when provided in - * order to send the appropriate scan commands to firmware to populate or - * update the internal driver scan table. - */ -int mwifiex_scan_networks(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg *user_scan_in) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node = NULL; - union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL; - struct mwifiex_ie_types_chan_list_param_set *chan_list_out; - u32 buf_size; - struct mwifiex_chan_scan_param_set *scan_chan_list; - u8 keep_previous_scan; - u8 filtered_scan; - u8 scan_current_chan_only; - u8 max_chan_per_scan; - unsigned long flags; - - if (adapter->scan_processing) { - dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); - return ret; - } - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = true; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - if (priv->scan_block) { - dev_dbg(adapter->dev, - "cmd: Scan is blocked during association...\n"); - return ret; - } - - scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv), - GFP_KERNEL); - if (!scan_cfg_out) { - dev_err(adapter->dev, "failed to alloc scan_cfg_out\n"); - return -1; - } - - buf_size = sizeof(struct mwifiex_chan_scan_param_set) * - MWIFIEX_USER_SCAN_CHAN_MAX; - scan_chan_list = kzalloc(buf_size, GFP_KERNEL); - if (!scan_chan_list) { - dev_err(adapter->dev, "failed to alloc scan_chan_list\n"); - kfree(scan_cfg_out); - return -1; - } - - keep_previous_scan = false; - - mwifiex_scan_setup_scan_config(priv, user_scan_in, - &scan_cfg_out->config, &chan_list_out, - scan_chan_list, &max_chan_per_scan, - &filtered_scan, &scan_current_chan_only); - - if (user_scan_in) - keep_previous_scan = user_scan_in->keep_previous_scan; - - - if (!keep_previous_scan) { - memset(adapter->scan_table, 0x00, - sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); - adapter->num_in_scan_table = 0; - adapter->bcn_buf_end = adapter->bcn_buf; - } - - ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, - &scan_cfg_out->config, chan_list_out, - scan_chan_list); - - /* Get scan command from scan_pending_q and put to cmd_pending_q */ - if (!ret) { - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - if (!list_empty(&adapter->scan_pending_q)) { - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, - true); - } else { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - } - } else { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = true; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - } - - kfree(scan_cfg_out); - kfree(scan_chan_list); - return ret; -} - -/* - * This function prepares a scan command to be sent to the firmware. - * - * This uses the scan command configuration sent to the command processing - * module in command preparation stage to configure a scan command structure - * to send to firmware. - * - * The fixed fields specifying the BSS type and BSSID filters as well as a - * variable number/length of TLVs are sent in the command to firmware. - * - * Preparation also includes - - * - Setting command ID, and proper size - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan; - struct mwifiex_scan_cmd_config *scan_cfg; - - scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf; - - /* Set fixed field variables in scan command */ - scan_cmd->bss_mode = scan_cfg->bss_mode; - memcpy(scan_cmd->bssid, scan_cfg->specific_bssid, - sizeof(scan_cmd->bssid)); - memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN); - - /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ - cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode) - + sizeof(scan_cmd->bssid) - + scan_cfg->tlv_buf_len + S_DS_GEN)); - - return 0; -} - -/* - * This function handles the command response of scan. - * - * The response buffer for the scan command has the following - * memory layout: - * - * .-------------------------------------------------------------. - * | Header (4 * sizeof(t_u16)): Standard command response hdr | - * .-------------------------------------------------------------. - * | BufSize (t_u16) : sizeof the BSS Description data | - * .-------------------------------------------------------------. - * | NumOfSet (t_u8) : Number of BSS Descs returned | - * .-------------------------------------------------------------. - * | BSSDescription data (variable, size given in BufSize) | - * .-------------------------------------------------------------. - * | TLV data (variable, size calculated using Header->Size, | - * | BufSize and sizeof the fixed fields above) | - * .-------------------------------------------------------------. - */ -int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node = NULL; - struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL; - struct mwifiex_bssdescriptor *bss_new_entry = NULL; - struct mwifiex_ie_types_data *tlv_data; - struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; - u8 *bss_info; - u32 scan_resp_size; - u32 bytes_left; - u32 num_in_table; - u32 bss_idx; - u32 idx; - u32 tlv_buf_size; - long long tsf_val; - struct mwifiex_chan_freq_power *cfp; - struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; - struct chan_band_param_set *chan_band; - u8 band; - u8 is_bgscan_resp; - unsigned long flags; - - is_bgscan_resp = (le16_to_cpu(resp->command) - == HostCmd_CMD_802_11_BG_SCAN_QUERY); - if (is_bgscan_resp) - scan_rsp = &resp->params.bg_scan_query_resp.scan_resp; - else - scan_rsp = &resp->params.scan_resp; - - - if (scan_rsp->number_of_sets > IW_MAX_AP) { - dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n", - scan_rsp->number_of_sets); - ret = -1; - goto done; - } - - bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); - dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", - bytes_left); - - scan_resp_size = le16_to_cpu(resp->size); - - dev_dbg(adapter->dev, - "info: SCAN_RESP: returned %d APs before parsing\n", - scan_rsp->number_of_sets); - - num_in_table = adapter->num_in_scan_table; - bss_info = scan_rsp->bss_desc_and_tlv_buffer; - - /* - * The size of the TLV buffer is equal to the entire command response - * size (scan_resp_size) minus the fixed fields (sizeof()'s), the - * BSS Descriptions (bss_descript_size as bytesLef) and the command - * response header (S_DS_GEN) - */ - tlv_buf_size = scan_resp_size - (bytes_left - + sizeof(scan_rsp->bss_descript_size) - + sizeof(scan_rsp->number_of_sets) - + S_DS_GEN); - - tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp-> - bss_desc_and_tlv_buffer + - bytes_left); - - /* Search the TLV buffer space in the scan response for any valid - TLVs */ - mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, - TLV_TYPE_TSFTIMESTAMP, - (struct mwifiex_ie_types_data **) - &tsf_tlv); - - /* Search the TLV buffer space in the scan response for any valid - TLVs */ - mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, - TLV_TYPE_CHANNELBANDLIST, - (struct mwifiex_ie_types_data **) - &chan_band_tlv); - - /* - * Process each scan response returned (scan_rsp->number_of_sets). - * Save the information in the bss_new_entry and then insert into the - * driver scan table either as an update to an existing entry - * or as an addition at the end of the table - */ - bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor), - GFP_KERNEL); - if (!bss_new_entry) { - dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); - return -1; - } - - for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { - /* Zero out the bss_new_entry we are about to store info in */ - memset(bss_new_entry, 0x00, - sizeof(struct mwifiex_bssdescriptor)); - - if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry, - &bss_info, - &bytes_left)) { - /* Error parsing/interpreting scan response, skipped */ - dev_err(adapter->dev, "SCAN_RESP: " - "mwifiex_interpret_bss_desc_with_ie " - "returned ERROR\n"); - continue; - } - - /* Process the data fields and IEs returned for this BSS */ - dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n", - bss_new_entry->mac_address); - - /* Search the scan table for the same bssid */ - for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) { - if (memcmp(bss_new_entry->mac_address, - adapter->scan_table[bss_idx].mac_address, - sizeof(bss_new_entry->mac_address))) { - continue; - } - /* - * If the SSID matches as well, it is a - * duplicate of this entry. Keep the bss_idx - * set to this entry so we replace the old - * contents in the table - */ - if ((bss_new_entry->ssid.ssid_len - == adapter->scan_table[bss_idx]. ssid.ssid_len) - && (!memcmp(bss_new_entry->ssid.ssid, - adapter->scan_table[bss_idx].ssid.ssid, - bss_new_entry->ssid.ssid_len))) { - dev_dbg(adapter->dev, "info: SCAN_RESP:" - " duplicate of index: %d\n", bss_idx); - break; - } - } - /* - * If the bss_idx is equal to the number of entries in - * the table, the new entry was not a duplicate; append - * it to the scan table - */ - if (bss_idx == num_in_table) { - /* Range check the bss_idx, keep it limited to - the last entry */ - if (bss_idx == IW_MAX_AP) - bss_idx--; - else - num_in_table++; - } - - /* - * Save the beacon/probe response returned for later application - * retrieval. Duplicate beacon/probe responses are updated if - * possible - */ - mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx, - num_in_table, bss_new_entry); - /* - * If the TSF TLV was appended to the scan results, save this - * entry's TSF value in the networkTSF field.The networkTSF is - * the firmware's TSF value at the time the beacon or probe - * response was received. - */ - if (tsf_tlv) { - memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE] - , sizeof(tsf_val)); - memcpy(&bss_new_entry->network_tsf, &tsf_val, - sizeof(bss_new_entry->network_tsf)); - } - band = BAND_G; - if (chan_band_tlv) { - chan_band = &chan_band_tlv->chan_band_param[idx]; - band = mwifiex_radio_type_to_band(chan_band->radio_type - & (BIT(0) | BIT(1))); - } - - /* Save the band designation for this entry for use in join */ - bss_new_entry->bss_band = band; - cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, - (u8) bss_new_entry->bss_band, - (u16)bss_new_entry->channel); - - if (cfp) - bss_new_entry->freq = cfp->freq; - else - bss_new_entry->freq = 0; - - /* Copy the locally created bss_new_entry to the scan table */ - memcpy(&adapter->scan_table[bss_idx], bss_new_entry, - sizeof(adapter->scan_table[bss_idx])); - - } - - dev_dbg(adapter->dev, - "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", - scan_rsp->number_of_sets, - num_in_table - adapter->num_in_scan_table, num_in_table); - - /* Update the total number of BSSIDs in the scan table */ - adapter->num_in_scan_table = num_in_table; - - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - if (list_empty(&adapter->scan_pending_q)) { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - /* - * Process the resulting scan table: - * - Remove any bad ssids - * - Update our current BSS information from scan data - */ - mwifiex_process_scan_results(priv); - - /* Need to indicate IOCTL complete */ - if (adapter->curr_cmd->wait_q_enabled) { - adapter->cmd_wait_q.status = 0; - mwifiex_complete_cmd(adapter); - } - if (priv->report_scan_result) - priv->report_scan_result = false; - if (priv->scan_pending_on_block) { - priv->scan_pending_on_block = false; - up(&priv->async_sem); - } - - } else { - /* Get scan command from scan_pending_q and put to - cmd_pending_q */ - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); - } - -done: - kfree((u8 *) bss_new_entry); - return ret; -} - -/* - * This function prepares command for background scan query. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting background scan flush parameter - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd) -{ - struct host_cmd_ds_802_11_bg_scan_query *bg_query = - &cmd->params.bg_scan_query; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query) - + S_DS_GEN); - - bg_query->flush = 1; - - return 0; -} - -/* - * This function finds a SSID in the scan table. - * - * A BSSID may optionally be provided to qualify the SSID. - * For non-Auto mode, further check is made to make sure the - * BSS found in the scan table is compatible with the current - * settings of the driver. - */ -s32 -mwifiex_find_ssid_in_list(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *ssid, u8 *bssid, - u32 mode) -{ - struct mwifiex_adapter *adapter = priv->adapter; - s32 net = -1, j; - u8 best_rssi = 0; - u32 i; - - dev_dbg(adapter->dev, "info: num of entries in table = %d\n", - adapter->num_in_scan_table); - - /* - * Loop through the table until the maximum is reached or until a match - * is found based on the bssid field comparison - */ - for (i = 0; - i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0)); - i++) { - if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) && - (!bssid - || !memcmp(adapter->scan_table[i].mac_address, bssid, - ETH_ALEN)) - && - (mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, (u8) adapter->scan_table[i].bss_band, - (u16) adapter->scan_table[i].channel))) { - switch (mode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - j = mwifiex_is_network_compatible(priv, i, - mode); - - if (j >= 0) { - if (SCAN_RSSI - (adapter->scan_table[i].rssi) > - best_rssi) { - best_rssi = SCAN_RSSI(adapter-> - scan_table - [i].rssi); - net = i; - } - } else { - if (net == -1) - net = j; - } - break; - case NL80211_IFTYPE_UNSPECIFIED: - default: - /* - * Do not check compatibility if the mode - * requested is Auto/Unknown. Allows generic - * find to work without verifying against the - * Adapter security settings - */ - if (SCAN_RSSI(adapter->scan_table[i].rssi) > - best_rssi) { - best_rssi = SCAN_RSSI(adapter-> - scan_table[i].rssi); - net = i; - } - break; - } - } - } - - return net; -} - -/* - * This function finds a specific compatible BSSID in the scan list. - * - * This function loops through the scan table looking for a compatible - * match. If a BSSID matches, but the BSS is found to be not compatible - * the function ignores it and continues to search through the rest of - * the entries in case there is an AP with multiple SSIDs assigned to - * the same BSSID. - */ -s32 -mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, - u32 mode) -{ - struct mwifiex_adapter *adapter = priv->adapter; - s32 net = -1; - u32 i; - - if (!bssid) - return -1; - - dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n", - adapter->num_in_scan_table); - - /* - * Look through the scan table for a compatible match. The ret return - * variable will be equal to the index in the scan table (greater - * than zero) if the network is compatible. The loop will continue - * past a matched bssid that is not compatible in case there is an - * AP with multiple SSIDs assigned to the same BSSID - */ - for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) { - if (!memcmp - (adapter->scan_table[i].mac_address, bssid, ETH_ALEN) - && mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, - (u8) adapter-> - scan_table[i]. - bss_band, - (u16) adapter-> - scan_table[i]. - channel)) { - switch (mode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - net = mwifiex_is_network_compatible(priv, i, - mode); - break; - default: - net = i; - break; - } - } - } - - return net; -} - -/* - * This function inserts scan command node to the scan pending queue. - */ -void -mwifiex_queue_scan_cmd(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node) -{ - struct mwifiex_adapter *adapter = priv->adapter; - unsigned long flags; - - cmd_node->wait_q_enabled = true; - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_add_tail(&cmd_node->list, &adapter->scan_pending_q); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -} - -/* - * This function finds an AP with specific ssid in the scan list. - */ -int mwifiex_find_best_network(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *req_ssid_bssid) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *req_bss; - s32 i; - - memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); - - i = mwifiex_find_best_network_in_list(priv); - - if (i >= 0) { - req_bss = &adapter->scan_table[i]; - memcpy(&req_ssid_bssid->ssid, &req_bss->ssid, - sizeof(struct mwifiex_802_11_ssid)); - memcpy((u8 *) &req_ssid_bssid->bssid, - (u8 *) &req_bss->mac_address, ETH_ALEN); - - /* Make sure we are in the right mode */ - if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) - priv->bss_mode = req_bss->bss_mode; - } - - if (!req_ssid_bssid->ssid.ssid_len) - return -1; - - dev_dbg(adapter->dev, "info: Best network found = [%s], " - "[%pM]\n", req_ssid_bssid->ssid.ssid, - req_ssid_bssid->bssid); - - return 0; -} - -/* - * This function sends a scan command for all available channels to the - * firmware, filtered on a specific SSID. - */ -static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *req_ssid) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - struct mwifiex_user_scan_cfg *scan_cfg; - - if (!req_ssid) - return -1; - - if (adapter->scan_processing) { - dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); - return ret; - } - - if (priv->scan_block) { - dev_dbg(adapter->dev, - "cmd: Scan is blocked during association...\n"); - return ret; - } - - mwifiex_scan_delete_ssid_table_entry(priv, req_ssid); - - scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); - if (!scan_cfg) { - dev_err(adapter->dev, "failed to alloc scan_cfg\n"); - return -1; - } - - memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, - req_ssid->ssid_len); - scan_cfg->keep_previous_scan = true; - - ret = mwifiex_scan_networks(priv, scan_cfg); - - kfree(scan_cfg); - return ret; -} - -/* - * Sends IOCTL request to start a scan. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - * - * Scan command can be issued for both normal scan and specific SSID - * scan, depending upon whether an SSID is provided or not. - */ -int mwifiex_request_scan(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *req_ssid) -{ - int ret = 0; - - if (down_interruptible(&priv->async_sem)) { - dev_err(priv->adapter->dev, "%s: acquire semaphore\n", - __func__); - return -1; - } - priv->scan_pending_on_block = true; - - priv->adapter->cmd_wait_q.condition = false; - - if (req_ssid && req_ssid->ssid_len != 0) - /* Specific SSID scan */ - ret = mwifiex_scan_specific_ssid(priv, req_ssid); - else - /* Normal scan */ - ret = mwifiex_scan_networks(priv, NULL); - - if (!ret) - ret = mwifiex_wait_queue_complete(priv->adapter); - - if (ret == -1) { - priv->scan_pending_on_block = false; - up(&priv->async_sem); - } - - return ret; -} - -/* - * This function appends the vendor specific IE TLV to a buffer. - */ -int -mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, - u16 vsie_mask, u8 **buffer) -{ - int id, ret_len = 0; - struct mwifiex_ie_types_vendor_param_set *vs_param_set; - - if (!buffer) - return 0; - if (!(*buffer)) - return 0; - - /* - * Traverse through the saved vendor specific IE array and append - * the selected(scan/assoc/adhoc) IE as TLV to the command - */ - for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) { - if (priv->vs_ie[id].mask & vsie_mask) { - vs_param_set = - (struct mwifiex_ie_types_vendor_param_set *) - *buffer; - vs_param_set->header.type = - cpu_to_le16(TLV_TYPE_PASSTHROUGH); - vs_param_set->header.len = - cpu_to_le16((((u16) priv->vs_ie[id].ie[1]) - & 0x00FF) + 2); - memcpy(vs_param_set->ie, priv->vs_ie[id].ie, - le16_to_cpu(vs_param_set->header.len)); - *buffer += le16_to_cpu(vs_param_set->header.len) + - sizeof(struct mwifiex_ie_types_header); - ret_len += le16_to_cpu(vs_param_set->header.len) + - sizeof(struct mwifiex_ie_types_header); - } - } - return ret_len; -} - -/* - * This function saves a beacon buffer of the current BSS descriptor. - * - * The current beacon buffer is saved so that it can be restored in the - * following cases that makes the beacon buffer not to contain the current - * ssid's beacon buffer. - * - The current ssid was not found somehow in the last scan. - * - The current ssid was the last entry of the scan table and overloaded. - */ -void -mwifiex_save_curr_bcn(struct mwifiex_private *priv) -{ - struct mwifiex_bssdescriptor *curr_bss = - &priv->curr_bss_params.bss_descriptor; - - if (!curr_bss->beacon_buf_size) - return; - - /* allocate beacon buffer at 1st time; or if it's size has changed */ - if (!priv->curr_bcn_buf || - priv->curr_bcn_size != curr_bss->beacon_buf_size) { - priv->curr_bcn_size = curr_bss->beacon_buf_size; - - kfree(priv->curr_bcn_buf); - priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size, - GFP_KERNEL); - if (!priv->curr_bcn_buf) { - dev_err(priv->adapter->dev, - "failed to alloc curr_bcn_buf\n"); - return; - } - } - - memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, - curr_bss->beacon_buf_size); - dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n", - priv->curr_bcn_size); -} - -/* - * This function frees the current BSS descriptor beacon buffer. - */ -void -mwifiex_free_curr_bcn(struct mwifiex_private *priv) -{ - kfree(priv->curr_bcn_buf); - priv->curr_bcn_buf = NULL; -} diff --git a/trunk/drivers/net/wireless/mwifiex/sdio.c b/trunk/drivers/net/wireless/mwifiex/sdio.c deleted file mode 100644 index 5148d0e0fad6..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sdio.c +++ /dev/null @@ -1,1753 +0,0 @@ -/* - * Marvell Wireless LAN device driver: SDIO specific handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "sdio.h" - - -#define SDIO_VERSION "1.0" - -static struct mwifiex_if_ops sdio_ops; - -static struct semaphore add_remove_card_sem; - -/* - * SDIO probe. - * - * This function probes an mwifiex device and registers it. It allocates - * the card structure, enables SDIO function number and initiates the - * device registration and initialization procedure by adding a logical - * interface. - */ -static int -mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) -{ - int ret = 0; - struct sdio_mmc_card *card = NULL; - - pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", - func->vendor, func->device, func->class, func->num); - - card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); - if (!card) { - pr_err("%s: failed to alloc memory\n", __func__); - return -ENOMEM; - } - - card->func = func; - - func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - - sdio_claim_host(func); - ret = sdio_enable_func(func); - sdio_release_host(func); - - if (ret) { - pr_err("%s: failed to enable function\n", __func__); - return -EIO; - } - - if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops)) { - pr_err("%s: add card failed\n", __func__); - kfree(card); - sdio_claim_host(func); - ret = sdio_disable_func(func); - sdio_release_host(func); - ret = -1; - } - - return ret; -} - -/* - * SDIO remove. - * - * This function removes the interface and frees up the card structure. - */ -static void -mwifiex_sdio_remove(struct sdio_func *func) -{ - struct sdio_mmc_card *card; - - pr_debug("info: SDIO func num=%d\n", func->num); - - if (func) { - card = sdio_get_drvdata(func); - if (card) { - mwifiex_remove_card(card->adapter, - &add_remove_card_sem); - kfree(card); - } - } -} - -/* - * SDIO suspend. - * - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not suspended, this function allocates and sends a host - * sleep activate request to the firmware and turns off the traffic. - */ -static int mwifiex_sdio_suspend(struct device *dev) -{ - struct sdio_func *func = dev_to_sdio_func(dev); - struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter = NULL; - mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; - int i; - int ret = 0; - - if (func) { - pm_flag = sdio_get_host_pm_caps(func); - pr_debug("cmd: %s: suspend: PM flag = 0x%x\n", - sdio_func_id(func), pm_flag); - if (!(pm_flag & MMC_PM_KEEP_POWER)) { - pr_err("%s: cannot remain alive while host is" - " suspended\n", sdio_func_id(func)); - return -ENOSYS; - } - - card = sdio_get_drvdata(func); - if (!card || !card->adapter) { - pr_err("suspend: invalid card or adapter\n"); - return 0; - } - } else { - pr_err("suspend: sdio_func is not specified\n"); - return 0; - } - - adapter = card->adapter; - - /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); - } - - /* Indicate device suspended */ - adapter->is_suspended = true; - - for (i = 0; i < adapter->priv_num; i++) - netif_carrier_off(adapter->priv[i]->netdev); - - return ret; -} - -/* - * SDIO resume. - * - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not resumed, this function turns on the traffic and - * sends a host sleep cancel request to the firmware. - */ -static int mwifiex_sdio_resume(struct device *dev) -{ - struct sdio_func *func = dev_to_sdio_func(dev); - struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter = NULL; - mmc_pm_flag_t pm_flag = 0; - int i; - - if (func) { - pm_flag = sdio_get_host_pm_caps(func); - card = sdio_get_drvdata(func); - if (!card || !card->adapter) { - pr_err("resume: invalid card or adapter\n"); - return 0; - } - } else { - pr_err("resume: sdio_func is not specified\n"); - return 0; - } - - adapter = card->adapter; - - if (!adapter->is_suspended) { - dev_warn(adapter->dev, "device already resumed\n"); - return 0; - } - - adapter->is_suspended = false; - - for (i = 0; i < adapter->priv_num; i++) - if (adapter->priv[i]->media_connected) - netif_carrier_on(adapter->priv[i]->netdev); - - /* Disable Host Sleep */ - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); - - return 0; -} - -/* Device ID for SD8787 */ -#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119) - -/* WLAN IDs */ -static const struct sdio_device_id mwifiex_ids[] = { - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)}, - {}, -}; - -MODULE_DEVICE_TABLE(sdio, mwifiex_ids); - -static const struct dev_pm_ops mwifiex_sdio_pm_ops = { - .suspend = mwifiex_sdio_suspend, - .resume = mwifiex_sdio_resume, -}; - -static struct sdio_driver mwifiex_sdio = { - .name = "mwifiex_sdio", - .id_table = mwifiex_ids, - .probe = mwifiex_sdio_probe, - .remove = mwifiex_sdio_remove, - .drv = { - .owner = THIS_MODULE, - .pm = &mwifiex_sdio_pm_ops, - } -}; - -/* - * This function writes data into SDIO card register. - */ -static int -mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u32 data) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = -1; - - sdio_claim_host(card->func); - sdio_writeb(card->func, (u8) data, reg, &ret); - sdio_release_host(card->func); - - return ret; -} - -/* - * This function reads data from SDIO card register. - */ -static int -mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = -1; - u8 val; - - sdio_claim_host(card->func); - val = sdio_readb(card->func, reg, &ret); - sdio_release_host(card->func); - - *data = val; - - return ret; -} - -/* - * This function writes multiple data into SDIO card memory. - * - * This does not work in suspended mode. - */ -static int -mwifiex_write_data_sync(struct mwifiex_adapter *adapter, - u8 *buffer, u32 pkt_len, u32 port) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = -1; - u8 blk_mode = - (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; - u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; - u32 blk_cnt = - (blk_mode == - BLOCK_MODE) ? (pkt_len / - MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len; - u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); - - if (adapter->is_suspended) { - dev_err(adapter->dev, - "%s: not allowed while suspended\n", __func__); - return -1; - } - - sdio_claim_host(card->func); - - if (!sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size)) - ret = 0; - - sdio_release_host(card->func); - - return ret; -} - -/* - * This function reads multiple data from SDIO card memory. - */ -static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, - u32 len, u32 port, u8 claim) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = -1; - u8 blk_mode = - (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; - u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; - u32 blk_cnt = - (blk_mode == - BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) : len; - u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); - - if (claim) - sdio_claim_host(card->func); - - if (!sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size)) - ret = 0; - - if (claim) - sdio_release_host(card->func); - - return ret; -} - -/* - * This function wakes up the card. - * - * A host power up command is written to the card configuration - * register to wake up the card. - */ -static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) -{ - dev_dbg(adapter->dev, "event: wakeup device...\n"); - - return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); -} - -/* - * This function is called after the card has woken up. - * - * The card configuration register is reset. - */ -static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) -{ - dev_dbg(adapter->dev, "cmd: wakeup device completed\n"); - - return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); -} - -/* - * This function initializes the IO ports. - * - * The following operations are performed - - * - Read the IO ports (0, 1 and 2) - * - Set host interrupt Reset-To-Read to clear - * - Set auto re-enable interrupt - */ -static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) -{ - u32 reg; - - adapter->ioport = 0; - - /* Read the IO port */ - if (!mwifiex_read_reg(adapter, IO_PORT_0_REG, ®)) - adapter->ioport |= (reg & 0xff); - else - return -1; - - if (!mwifiex_read_reg(adapter, IO_PORT_1_REG, ®)) - adapter->ioport |= ((reg & 0xff) << 8); - else - return -1; - - if (!mwifiex_read_reg(adapter, IO_PORT_2_REG, ®)) - adapter->ioport |= ((reg & 0xff) << 16); - else - return -1; - - pr_debug("info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); - - /* Set Host interrupt reset to read to clear */ - if (!mwifiex_read_reg(adapter, HOST_INT_RSR_REG, ®)) - mwifiex_write_reg(adapter, HOST_INT_RSR_REG, - reg | SDIO_INT_MASK); - else - return -1; - - /* Dnld/Upld ready set to auto reset */ - if (!mwifiex_read_reg(adapter, CARD_MISC_CFG_REG, ®)) - mwifiex_write_reg(adapter, CARD_MISC_CFG_REG, - reg | AUTO_RE_ENABLE_INT); - else - return -1; - - return 0; -} - -/* - * This function sends data to the card. - */ -static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, - u8 *payload, u32 pkt_len, u32 port) -{ - u32 i = 0; - int ret = 0; - - do { - ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); - if (ret) { - i++; - dev_err(adapter->dev, "host_to_card, write iomem" - " (%d) failed: %d\n", i, ret); - if (mwifiex_write_reg(adapter, - CONFIGURATION_REG, 0x04)) - dev_err(adapter->dev, "write CFG reg failed\n"); - - ret = -1; - if (i > MAX_WRITE_IOMEM_RETRY) - return ret; - } - } while (ret == -1); - - return ret; -} - -/* - * This function gets the read port. - * - * If control port bit is set in MP read bitmap, the control port - * is returned, otherwise the current read port is returned and - * the value is increased (provided it does not reach the maximum - * limit, in which case it is reset to 1) - */ -static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) -{ - struct sdio_mmc_card *card = adapter->card; - u16 rd_bitmap = card->mp_rd_bitmap; - - dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%04x\n", rd_bitmap); - - if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK))) - return -1; - - if (card->mp_rd_bitmap & CTRL_PORT_MASK) { - card->mp_rd_bitmap &= (u16) (~CTRL_PORT_MASK); - *port = CTRL_PORT; - dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%04x\n", - *port, card->mp_rd_bitmap); - } else { - if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) { - card->mp_rd_bitmap &= - (u16) (~(1 << card->curr_rd_port)); - *port = card->curr_rd_port; - - if (++card->curr_rd_port == MAX_PORT) - card->curr_rd_port = 1; - } else { - return -1; - } - - dev_dbg(adapter->dev, - "data: port=%d mp_rd_bitmap=0x%04x -> 0x%04x\n", - *port, rd_bitmap, card->mp_rd_bitmap); - } - return 0; -} - -/* - * This function gets the write port for data. - * - * The current write port is returned if available and the value is - * increased (provided it does not reach the maximum limit, in which - * case it is reset to 1) - */ -static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) -{ - struct sdio_mmc_card *card = adapter->card; - u16 wr_bitmap = card->mp_wr_bitmap; - - dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%04x\n", wr_bitmap); - - if (!(wr_bitmap & card->mp_data_port_mask)) - return -1; - - if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { - card->mp_wr_bitmap &= (u16) (~(1 << card->curr_wr_port)); - *port = card->curr_wr_port; - if (++card->curr_wr_port == card->mp_end_port) - card->curr_wr_port = 1; - } else { - adapter->data_sent = true; - return -EBUSY; - } - - if (*port == CTRL_PORT) { - dev_err(adapter->dev, "invalid data port=%d cur port=%d" - " mp_wr_bitmap=0x%04x -> 0x%04x\n", - *port, card->curr_wr_port, wr_bitmap, - card->mp_wr_bitmap); - return -1; - } - - dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%04x -> 0x%04x\n", - *port, wr_bitmap, card->mp_wr_bitmap); - - return 0; -} - -/* - * This function polls the card status. - */ -static int -mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) -{ - u32 tries; - u32 cs = 0; - - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) - break; - else if ((cs & bits) == bits) - return 0; - - udelay(10); - } - - dev_err(adapter->dev, "poll card status failed, tries = %d\n", - tries); - return -1; -} - -/* - * This function reads the firmware status. - */ -static int -mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) -{ - u32 fws0 = 0, fws1 = 0; - - if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) - return -1; - - if (mwifiex_read_reg(adapter, CARD_FW_STATUS1_REG, &fws1)) - return -1; - - *dat = (u16) ((fws1 << 8) | fws0); - - return 0; -} - -/* - * This function disables the host interrupt. - * - * The host interrupt mask is read, the disable bit is reset and - * written back to the card host interrupt mask register. - */ -static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) -{ - u32 host_int_mask = 0; - - /* Read back the host_int_mask register */ - if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) - return -1; - - /* Update with the mask and write back to the register */ - host_int_mask &= ~HOST_INT_DISABLE; - - if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) { - dev_err(adapter->dev, "disable host interrupt failed\n"); - return -1; - } - - return 0; -} - -/* - * This function enables the host interrupt. - * - * The host interrupt enable mask is written to the card - * host interrupt mask register. - */ -static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) -{ - /* Simply write the mask to the register */ - if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, HOST_INT_ENABLE)) { - dev_err(adapter->dev, "enable host interrupt failed\n"); - return -1; - } - return 0; -} - -/* - * This function sends a data buffer to the card. - */ -static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, - u32 *type, u8 *buffer, - u32 npayload, u32 ioport) -{ - int ret = 0; - u32 nb; - - if (!buffer) { - dev_err(adapter->dev, "%s: buffer is NULL\n", __func__); - return -1; - } - - ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1); - - if (ret) { - dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__, - ret); - return -1; - } - - nb = le16_to_cpu(*(__le16 *) (buffer)); - if (nb > npayload) { - dev_err(adapter->dev, "%s: invalid packet, nb=%d, npayload=%d\n", - __func__, nb, npayload); - return -1; - } - - *type = le16_to_cpu(*(__le16 *) (buffer + 2)); - - return ret; -} - -/* - * This function downloads the firmware to the card. - * - * Firmware is downloaded to the card in blocks. Every block download - * is tested for CRC errors, and retried a number of times before - * returning failure. - */ -static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *fw) -{ - int ret = 0; - u8 *firmware = fw->fw_buf; - u32 firmware_len = fw->fw_len; - u32 offset = 0; - u32 base0, base1; - u8 *fwbuf; - u16 len = 0; - u32 txlen = 0, tx_blocks = 0, tries = 0; - u32 i = 0; - - if (!firmware_len) { - dev_err(adapter->dev, "firmware image not found!" - " Terminating download\n"); - return -1; - } - - dev_dbg(adapter->dev, "info: downloading FW image (%d bytes)\n", - firmware_len); - - /* Assume that the allocated buffer is 8-byte aligned */ - fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL); - if (!fwbuf) { - dev_err(adapter->dev, "unable to alloc buffer for firmware." - " Terminating download\n"); - return -1; - } - - /* Perform firmware data transfer */ - do { - /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY - bits */ - ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY | - DN_LD_CARD_RDY); - if (ret) { - dev_err(adapter->dev, "FW download with helper:" - " poll status timeout @ %d\n", offset); - goto done; - } - - /* More data? */ - if (offset >= firmware_len) - break; - - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_0, - &base0); - if (ret) { - dev_err(adapter->dev, "dev BASE0 register read" - " failed: base0=0x%04X(%d). Terminating " - "download\n", base0, base0); - goto done; - } - ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_1, - &base1); - if (ret) { - dev_err(adapter->dev, "dev BASE1 register read" - " failed: base1=0x%04X(%d). Terminating " - "download\n", base1, base1); - goto done; - } - len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff)); - - if (len) - break; - - udelay(10); - } - - if (!len) { - break; - } else if (len > MWIFIEX_UPLD_SIZE) { - dev_err(adapter->dev, "FW download failed @ %d," - " invalid length %d\n", offset, len); - ret = -1; - goto done; - } - - txlen = len; - - if (len & BIT(0)) { - i++; - if (i > MAX_WRITE_IOMEM_RETRY) { - dev_err(adapter->dev, "FW download failed @" - " %d, over max retry count\n", offset); - ret = -1; - goto done; - } - dev_err(adapter->dev, "CRC indicated by the helper:" - " len = 0x%04X, txlen = %d\n", len, txlen); - len &= ~BIT(0); - /* Setting this to 0 to resend from same offset */ - txlen = 0; - } else { - i = 0; - - /* Set blocksize to transfer - checking for last - block */ - if (firmware_len - offset < txlen) - txlen = firmware_len - offset; - - tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - - 1) / MWIFIEX_SDIO_BLOCK_SIZE; - - /* Copy payload to buffer */ - memmove(fwbuf, &firmware[offset], txlen); - } - - ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks * - MWIFIEX_SDIO_BLOCK_SIZE, - adapter->ioport); - if (ret) { - dev_err(adapter->dev, "FW download, write iomem (%d)" - " failed @ %d\n", i, offset); - if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04)) - dev_err(adapter->dev, "write CFG reg failed\n"); - - ret = -1; - goto done; - } - - offset += txlen; - } while (true); - - dev_dbg(adapter->dev, "info: FW download over, size %d bytes\n", - offset); - - ret = 0; -done: - kfree(fwbuf); - return ret; -} - -/* - * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. - */ -static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, - u32 poll_num, int *winner) -{ - int ret = 0; - u16 firmware_stat; - u32 tries; - u32 winner_status; - - /* Wait for firmware initialization event */ - for (tries = 0; tries < poll_num; tries++) { - ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); - if (ret) - continue; - if (firmware_stat == FIRMWARE_READY) { - ret = 0; - break; - } else { - mdelay(100); - ret = -1; - } - } - - if (winner && ret) { - if (mwifiex_read_reg - (adapter, CARD_FW_STATUS0_REG, &winner_status)) - winner_status = 0; - - if (winner_status) - *winner = 0; - else - *winner = 1; - } - return ret; -} - -/* - * This function reads the interrupt status from card. - */ -static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - u32 sdio_ireg = 0; - unsigned long flags; - - if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, - REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, - 0)) { - dev_err(adapter->dev, "read mp_regs failed\n"); - return; - } - - sdio_ireg = card->mp_regs[HOST_INTSTATUS_REG]; - if (sdio_ireg) { - /* - * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS - * Clear the interrupt status register - */ - dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg); - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= sdio_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - } -} - -/* - * SDIO interrupt handler. - * - * This function reads the interrupt status from firmware and assigns - * the main process in workqueue which will handle the interrupt. - */ -static void -mwifiex_sdio_interrupt(struct sdio_func *func) -{ - struct mwifiex_adapter *adapter; - struct sdio_mmc_card *card; - - card = sdio_get_drvdata(func); - if (!card || !card->adapter) { - pr_debug("int: func=%p card=%p adapter=%p\n", - func, card, card ? card->adapter : NULL); - return; - } - adapter = card->adapter; - - if (adapter->surprise_removed) - return; - - if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) - adapter->ps_state = PS_STATE_AWAKE; - - mwifiex_interrupt_status(adapter); - queue_work(adapter->workqueue, &adapter->main_work); -} - -/* - * This function decodes a received packet. - * - * Based on the type, the packet is treated as either a data, or - * a command response, or an event, and the correct handler - * function is invoked. - */ -static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb, u32 upld_typ) -{ - u8 *cmd_buf; - - skb_pull(skb, INTF_HEADER_LEN); - - switch (upld_typ) { - case MWIFIEX_TYPE_DATA: - dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); - mwifiex_handle_rx_packet(adapter, skb); - break; - - case MWIFIEX_TYPE_CMD: - dev_dbg(adapter->dev, "info: --- Rx: Cmd Response ---\n"); - /* take care of curr_cmd = NULL case */ - if (!adapter->curr_cmd) { - cmd_buf = adapter->upld_buf; - - if (adapter->ps_state == PS_STATE_SLEEP_CFM) - mwifiex_process_sleep_confirm_resp(adapter, - skb->data, skb->len); - - memcpy(cmd_buf, skb->data, min_t(u32, - MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); - - dev_kfree_skb_any(skb); - } else { - adapter->cmd_resp_received = true; - adapter->curr_cmd->resp_skb = skb; - } - break; - - case MWIFIEX_TYPE_EVENT: - dev_dbg(adapter->dev, "info: --- Rx: Event ---\n"); - adapter->event_cause = *(u32 *) skb->data; - - skb_pull(skb, MWIFIEX_EVENT_HEADER_LEN); - - if ((skb->len > 0) && (skb->len < MAX_EVENT_SIZE)) - memcpy(adapter->event_body, skb->data, skb->len); - - /* event cause has been saved to adapter->event_cause */ - adapter->event_received = true; - adapter->event_skb = skb; - - break; - - default: - dev_err(adapter->dev, "unknown upload type %#x\n", upld_typ); - dev_kfree_skb_any(skb); - break; - } - - return 0; -} - -/* - * This function transfers received packets from card to driver, performing - * aggregation if required. - * - * For data received on control port, or if aggregation is disabled, the - * received buffers are uploaded as separate packets. However, if aggregation - * is enabled and required, the buffers are copied onto an aggregation buffer, - * provided there is space left, processed and finally uploaded. - */ -static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, - struct sk_buff *skb, u8 port) -{ - struct sdio_mmc_card *card = adapter->card; - s32 f_do_rx_aggr = 0; - s32 f_do_rx_cur = 0; - s32 f_aggr_cur = 0; - struct sk_buff *skb_deaggr; - u32 pind = 0; - u32 pkt_len, pkt_type = 0; - u8 *curr_ptr; - u32 rx_len = skb->len; - - if (port == CTRL_PORT) { - /* Read the command Resp without aggr */ - dev_dbg(adapter->dev, "info: %s: no aggregation for cmd " - "response\n", __func__); - - f_do_rx_cur = 1; - goto rx_curr_single; - } - - if (!card->mpa_rx.enabled) { - dev_dbg(adapter->dev, "info: %s: rx aggregation disabled\n", - __func__); - - f_do_rx_cur = 1; - goto rx_curr_single; - } - - if (card->mp_rd_bitmap & (~((u16) CTRL_PORT_MASK))) { - /* Some more data RX pending */ - dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); - - if (MP_RX_AGGR_IN_PROGRESS(card)) { - if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) { - f_aggr_cur = 1; - } else { - /* No room in Aggr buf, do rx aggr now */ - f_do_rx_aggr = 1; - f_do_rx_cur = 1; - } - } else { - /* Rx aggr not in progress */ - f_aggr_cur = 1; - } - - } else { - /* No more data RX pending */ - dev_dbg(adapter->dev, "info: %s: last packet\n", __func__); - - if (MP_RX_AGGR_IN_PROGRESS(card)) { - f_do_rx_aggr = 1; - if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) - f_aggr_cur = 1; - else - /* No room in Aggr buf, do rx aggr now */ - f_do_rx_cur = 1; - } else { - f_do_rx_cur = 1; - } - } - - if (f_aggr_cur) { - dev_dbg(adapter->dev, "info: current packet aggregation\n"); - /* Curr pkt can be aggregated */ - MP_RX_AGGR_SETUP(card, skb, port); - - if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || - MP_RX_AGGR_PORT_LIMIT_REACHED(card)) { - dev_dbg(adapter->dev, "info: %s: aggregated packet " - "limit reached\n", __func__); - /* No more pkts allowed in Aggr buf, rx it */ - f_do_rx_aggr = 1; - } - } - - if (f_do_rx_aggr) { - /* do aggr RX now */ - dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n", - card->mpa_rx.pkt_cnt); - - if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, - card->mpa_rx.buf_len, - (adapter->ioport | 0x1000 | - (card->mpa_rx.ports << 4)) + - card->mpa_rx.start_port, 1)) - return -1; - - curr_ptr = card->mpa_rx.buf; - - for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { - - /* get curr PKT len & type */ - pkt_len = *(u16 *) &curr_ptr[0]; - pkt_type = *(u16 *) &curr_ptr[2]; - - /* copy pkt to deaggr buf */ - skb_deaggr = card->mpa_rx.skb_arr[pind]; - - if ((pkt_type == MWIFIEX_TYPE_DATA) && (pkt_len <= - card->mpa_rx.len_arr[pind])) { - - memcpy(skb_deaggr->data, curr_ptr, pkt_len); - - skb_trim(skb_deaggr, pkt_len); - - /* Process de-aggr packet */ - mwifiex_decode_rx_packet(adapter, skb_deaggr, - pkt_type); - } else { - dev_err(adapter->dev, "wrong aggr pkt:" - " type=%d len=%d max_len=%d\n", - pkt_type, pkt_len, - card->mpa_rx.len_arr[pind]); - dev_kfree_skb_any(skb_deaggr); - } - curr_ptr += card->mpa_rx.len_arr[pind]; - } - MP_RX_AGGR_BUF_RESET(card); - } - -rx_curr_single: - if (f_do_rx_cur) { - dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", - port, rx_len); - - if (mwifiex_sdio_card_to_host(adapter, &pkt_type, - skb->data, skb->len, - adapter->ioport + port)) - return -1; - - mwifiex_decode_rx_packet(adapter, skb, pkt_type); - } - - return 0; -} - -/* - * This function checks the current interrupt status. - * - * The following interrupts are checked and handled by this function - - * - Data sent - * - Command sent - * - Packets received - * - * Since the firmware does not generate download ready interrupt if the - * port updated is command port only, command sent interrupt checking - * should be done manually, and for every SDIO interrupt. - * - * In case of Rx packets received, the packets are uploaded from card to - * host and processed accordingly. - */ -static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - u8 sdio_ireg; - struct sk_buff *skb = NULL; - u8 port = CTRL_PORT; - u32 len_reg_l, len_reg_u; - u32 rx_blocks; - u16 rx_len; - unsigned long flags; - - spin_lock_irqsave(&adapter->int_lock, flags); - sdio_ireg = adapter->int_status; - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); - - if (!sdio_ireg) - return ret; - - if (sdio_ireg & DN_LD_HOST_INT_STATUS) { - card->mp_wr_bitmap = ((u16) card->mp_regs[WR_BITMAP_U]) << 8; - card->mp_wr_bitmap |= (u16) card->mp_regs[WR_BITMAP_L]; - dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%04x\n", - card->mp_wr_bitmap); - if (adapter->data_sent && - (card->mp_wr_bitmap & card->mp_data_port_mask)) { - dev_dbg(adapter->dev, - "info: <--- Tx DONE Interrupt --->\n"); - adapter->data_sent = false; - } - } - - /* As firmware will not generate download ready interrupt if the port - updated is command port only, cmd_sent should be done for any SDIO - interrupt. */ - if (adapter->cmd_sent) { - /* Check if firmware has attach buffer at command port and - update just that in wr_bit_map. */ - card->mp_wr_bitmap |= - (u16) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; - if (card->mp_wr_bitmap & CTRL_PORT_MASK) - adapter->cmd_sent = false; - } - - dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", - adapter->cmd_sent, adapter->data_sent); - if (sdio_ireg & UP_LD_HOST_INT_STATUS) { - card->mp_rd_bitmap = ((u16) card->mp_regs[RD_BITMAP_U]) << 8; - card->mp_rd_bitmap |= (u16) card->mp_regs[RD_BITMAP_L]; - dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%04x\n", - card->mp_rd_bitmap); - - while (true) { - ret = mwifiex_get_rd_port(adapter, &port); - if (ret) { - dev_dbg(adapter->dev, - "info: no more rd_port available\n"); - break; - } - len_reg_l = RD_LEN_P0_L + (port << 1); - len_reg_u = RD_LEN_P0_U + (port << 1); - rx_len = ((u16) card->mp_regs[len_reg_u]) << 8; - rx_len |= (u16) card->mp_regs[len_reg_l]; - dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n", - port, rx_len); - rx_blocks = - (rx_len + MWIFIEX_SDIO_BLOCK_SIZE - - 1) / MWIFIEX_SDIO_BLOCK_SIZE; - if (rx_len <= INTF_HEADER_LEN - || (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > - MWIFIEX_RX_DATA_BUF_SIZE) { - dev_err(adapter->dev, "invalid rx_len=%d\n", - rx_len); - return -1; - } - rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); - - skb = dev_alloc_skb(rx_len); - - if (!skb) { - dev_err(adapter->dev, "%s: failed to alloc skb", - __func__); - return -1; - } - - skb_put(skb, rx_len); - - dev_dbg(adapter->dev, "info: rx_len = %d skb->len = %d\n", - rx_len, skb->len); - - if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, - port)) { - u32 cr = 0; - - dev_err(adapter->dev, "card_to_host_mpa failed:" - " int status=%#x\n", sdio_ireg); - if (mwifiex_read_reg(adapter, - CONFIGURATION_REG, &cr)) - dev_err(adapter->dev, - "read CFG reg failed\n"); - - dev_dbg(adapter->dev, - "info: CFG reg val = %d\n", cr); - if (mwifiex_write_reg(adapter, - CONFIGURATION_REG, - (cr | 0x04))) - dev_err(adapter->dev, - "write CFG reg failed\n"); - - dev_dbg(adapter->dev, "info: write success\n"); - if (mwifiex_read_reg(adapter, - CONFIGURATION_REG, &cr)) - dev_err(adapter->dev, - "read CFG reg failed\n"); - - dev_dbg(adapter->dev, - "info: CFG reg val =%x\n", cr); - dev_kfree_skb_any(skb); - return -1; - } - } - } - - return 0; -} - -/* - * This function aggregates transmission buffers in driver and downloads - * the aggregated packet to card. - * - * The individual packets are aggregated by copying into an aggregation - * buffer and then downloaded to the card. Previous unsent packets in the - * aggregation buffer are pre-copied first before new packets are added. - * Aggregation is done till there is space left in the aggregation buffer, - * or till new packets are available. - * - * The function will only download the packet to the card when aggregation - * stops, otherwise it will just aggregate the packet in aggregation buffer - * and return. - */ -static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, - u8 *payload, u32 pkt_len, u8 port, - u32 next_pkt_len) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - s32 f_send_aggr_buf = 0; - s32 f_send_cur_buf = 0; - s32 f_precopy_cur_buf = 0; - s32 f_postcopy_cur_buf = 0; - - if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) { - dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n", - __func__); - - f_send_cur_buf = 1; - goto tx_curr_single; - } - - if (next_pkt_len) { - /* More pkt in TX queue */ - dev_dbg(adapter->dev, "info: %s: more packets in queue.\n", - __func__); - - if (MP_TX_AGGR_IN_PROGRESS(card)) { - if (!MP_TX_AGGR_PORT_LIMIT_REACHED(card) && - MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) { - f_precopy_cur_buf = 1; - - if (!(card->mp_wr_bitmap & - (1 << card->curr_wr_port)) - || !MP_TX_AGGR_BUF_HAS_ROOM( - card, next_pkt_len)) - f_send_aggr_buf = 1; - } else { - /* No room in Aggr buf, send it */ - f_send_aggr_buf = 1; - - if (MP_TX_AGGR_PORT_LIMIT_REACHED(card) || - !(card->mp_wr_bitmap & - (1 << card->curr_wr_port))) - f_send_cur_buf = 1; - else - f_postcopy_cur_buf = 1; - } - } else { - if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) - && (card->mp_wr_bitmap & (1 << card->curr_wr_port))) - f_precopy_cur_buf = 1; - else - f_send_cur_buf = 1; - } - } else { - /* Last pkt in TX queue */ - dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n", - __func__); - - if (MP_TX_AGGR_IN_PROGRESS(card)) { - /* some packs in Aggr buf already */ - f_send_aggr_buf = 1; - - if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) - f_precopy_cur_buf = 1; - else - /* No room in Aggr buf, send it */ - f_send_cur_buf = 1; - } else { - f_send_cur_buf = 1; - } - } - - if (f_precopy_cur_buf) { - dev_dbg(adapter->dev, "data: %s: precopy current buffer\n", - __func__); - MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); - - if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) || - MP_TX_AGGR_PORT_LIMIT_REACHED(card)) - /* No more pkts allowed in Aggr buf, send it */ - f_send_aggr_buf = 1; - } - - if (f_send_aggr_buf) { - dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n", - __func__, - card->mpa_tx.start_port, card->mpa_tx.ports); - ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, - card->mpa_tx.buf_len, - (adapter->ioport | 0x1000 | - (card->mpa_tx.ports << 4)) + - card->mpa_tx.start_port); - - MP_TX_AGGR_BUF_RESET(card); - } - -tx_curr_single: - if (f_send_cur_buf) { - dev_dbg(adapter->dev, "data: %s: send current buffer %d\n", - __func__, port); - ret = mwifiex_write_data_to_card(adapter, payload, pkt_len, - adapter->ioport + port); - } - - if (f_postcopy_cur_buf) { - dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n", - __func__); - MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); - } - - return ret; -} - -/* - * This function downloads data from driver to card. - * - * Both commands and data packets are transferred to the card by this - * function. - * - * This function adds the SDIO specific header to the front of the buffer - * before transferring. The header contains the length of the packet and - * the type. The firmware handles the packets based upon this set type. - */ -static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, - u8 type, u8 *payload, u32 pkt_len, - struct mwifiex_tx_param *tx_param) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - u32 buf_block_len; - u32 blk_size; - u8 port = CTRL_PORT; - - /* Allocate buffer and copy payload */ - blk_size = MWIFIEX_SDIO_BLOCK_SIZE; - buf_block_len = (pkt_len + blk_size - 1) / blk_size; - *(u16 *) &payload[0] = (u16) pkt_len; - *(u16 *) &payload[2] = type; - - /* - * This is SDIO specific header - * u16 length, - * u16 type (MWIFIEX_TYPE_DATA = 0, MWIFIEX_TYPE_CMD = 1, - * MWIFIEX_TYPE_EVENT = 3) - */ - if (type == MWIFIEX_TYPE_DATA) { - ret = mwifiex_get_wr_port_data(adapter, &port); - if (ret) { - dev_err(adapter->dev, "%s: no wr_port available\n", - __func__); - return ret; - } - } else { - adapter->cmd_sent = true; - /* Type must be MWIFIEX_TYPE_CMD */ - - if (pkt_len <= INTF_HEADER_LEN || - pkt_len > MWIFIEX_UPLD_SIZE) - dev_err(adapter->dev, "%s: payload=%p, nb=%d\n", - __func__, payload, pkt_len); - } - - /* Transfer data to card */ - pkt_len = buf_block_len * blk_size; - - if (tx_param) - ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, - port, tx_param->next_pkt_len); - else - ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, - port, 0); - - if (ret) { - if (type == MWIFIEX_TYPE_CMD) - adapter->cmd_sent = false; - if (type == MWIFIEX_TYPE_DATA) - adapter->data_sent = false; - } else { - if (type == MWIFIEX_TYPE_DATA) { - if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) - adapter->data_sent = true; - else - adapter->data_sent = false; - } - } - - return ret; -} - -/* - * This function allocates the MPA Tx and Rx buffers. - */ -static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, - u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - - card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); - if (!card->mpa_tx.buf) { - dev_err(adapter->dev, "could not alloc buffer for MP-A TX\n"); - ret = -1; - goto error; - } - - card->mpa_tx.buf_size = mpa_tx_buf_size; - - card->mpa_rx.buf = kzalloc(mpa_rx_buf_size, GFP_KERNEL); - if (!card->mpa_rx.buf) { - dev_err(adapter->dev, "could not alloc buffer for MP-A RX\n"); - ret = -1; - goto error; - } - - card->mpa_rx.buf_size = mpa_rx_buf_size; - -error: - if (ret) { - kfree(card->mpa_tx.buf); - kfree(card->mpa_rx.buf); - } - - return ret; -} - -/* - * This function unregisters the SDIO device. - * - * The SDIO IRQ is released, the function is disabled and driver - * data is set to null. - */ -static void -mwifiex_unregister_dev(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - if (adapter->card) { - /* Release the SDIO IRQ */ - sdio_claim_host(card->func); - sdio_release_irq(card->func); - sdio_disable_func(card->func); - sdio_release_host(card->func); - sdio_set_drvdata(card->func, NULL); - } -} - -/* - * This function registers the SDIO device. - * - * SDIO IRQ is claimed, block size is set and driver data is initialized. - */ -static int mwifiex_register_dev(struct mwifiex_adapter *adapter) -{ - int ret = 0; - struct sdio_mmc_card *card = adapter->card; - struct sdio_func *func = card->func; - - /* save adapter pointer in card */ - card->adapter = adapter; - - sdio_claim_host(func); - - /* Request the SDIO IRQ */ - ret = sdio_claim_irq(func, mwifiex_sdio_interrupt); - if (ret) { - pr_err("claim irq failed: ret=%d\n", ret); - goto disable_func; - } - - /* Set block size */ - ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); - if (ret) { - pr_err("cannot set SDIO block size\n"); - ret = -1; - goto release_irq; - } - - sdio_release_host(func); - sdio_set_drvdata(func, card); - - adapter->dev = &func->dev; - - return 0; - -release_irq: - sdio_release_irq(func); -disable_func: - sdio_disable_func(func); - sdio_release_host(func); - adapter->card = NULL; - - return -1; -} - -/* - * This function initializes the SDIO driver. - * - * The following initializations steps are followed - - * - Read the Host interrupt status register to acknowledge - * the first interrupt got from bootloader - * - Disable host interrupt mask register - * - Get SDIO port - * - Get revision ID - * - Initialize SDIO variables in card - * - Allocate MP registers - * - Allocate MPA Tx and Rx buffers - */ -static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - u32 sdio_ireg = 0; - - /* - * Read the HOST_INT_STATUS_REG for ACK the first interrupt got - * from the bootloader. If we don't do this we get a interrupt - * as soon as we register the irq. - */ - mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg); - - /* Disable host interrupt mask register for SDIO */ - mwifiex_sdio_disable_host_int(adapter); - - /* Get SDIO ioport */ - mwifiex_init_sdio_ioport(adapter); - - /* Get revision ID */ -#define REV_ID_REG 0x5c - mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id); - - /* Initialize SDIO variables in card */ - card->mp_rd_bitmap = 0; - card->mp_wr_bitmap = 0; - card->curr_rd_port = 1; - card->curr_wr_port = 1; - - card->mp_data_port_mask = DATA_PORT_MASK; - - card->mpa_tx.buf_len = 0; - card->mpa_tx.pkt_cnt = 0; - card->mpa_tx.start_port = 0; - - card->mpa_tx.enabled = 0; - card->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; - - card->mpa_rx.buf_len = 0; - card->mpa_rx.pkt_cnt = 0; - card->mpa_rx.start_port = 0; - - card->mpa_rx.enabled = 0; - card->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; - - /* Allocate buffers for SDIO MP-A */ - card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); - if (!card->mp_regs) { - dev_err(adapter->dev, "failed to alloc mp_regs\n"); - return -1; - } - - ret = mwifiex_alloc_sdio_mpa_buffers(adapter, - SDIO_MP_TX_AGGR_DEF_BUF_SIZE, - SDIO_MP_RX_AGGR_DEF_BUF_SIZE); - if (ret) { - dev_err(adapter->dev, "failed to alloc sdio mp-a buffers\n"); - kfree(card->mp_regs); - return -1; - } - - return ret; -} - -/* - * This function resets the MPA Tx and Rx buffers. - */ -static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - MP_TX_AGGR_BUF_RESET(card); - MP_RX_AGGR_BUF_RESET(card); -} - -/* - * This function cleans up the allocated card buffers. - * - * The following are freed by this function - - * - MP registers - * - MPA Tx buffer - * - MPA Rx buffer - */ -static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - kfree(card->mp_regs); - kfree(card->mpa_tx.buf); - kfree(card->mpa_rx.buf); -} - -/* - * This function updates the MP end port in card. - */ -static void -mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) -{ - struct sdio_mmc_card *card = adapter->card; - int i; - - card->mp_end_port = port; - - card->mp_data_port_mask = DATA_PORT_MASK; - - for (i = 1; i <= MAX_PORT - card->mp_end_port; i++) - card->mp_data_port_mask &= ~(1 << (MAX_PORT - i)); - - card->curr_wr_port = 1; - - dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n", - port, card->mp_data_port_mask); -} - -static struct mwifiex_if_ops sdio_ops = { - .init_if = mwifiex_init_sdio, - .cleanup_if = mwifiex_cleanup_sdio, - .check_fw_status = mwifiex_check_fw_status, - .prog_fw = mwifiex_prog_fw_w_helper, - .register_dev = mwifiex_register_dev, - .unregister_dev = mwifiex_unregister_dev, - .enable_int = mwifiex_sdio_enable_host_int, - .process_int_status = mwifiex_process_int_status, - .host_to_card = mwifiex_sdio_host_to_card, - .wakeup = mwifiex_pm_wakeup_card, - .wakeup_complete = mwifiex_pm_wakeup_card_complete, - - /* SDIO specific */ - .update_mp_end_port = mwifiex_update_mp_end_port, - .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf, -}; - -/* - * This function initializes the SDIO driver. - * - * This initiates the semaphore and registers the device with - * SDIO bus. - */ -static int -mwifiex_sdio_init_module(void) -{ - sema_init(&add_remove_card_sem, 1); - - return sdio_register_driver(&mwifiex_sdio); -} - -/* - * This function cleans up the SDIO driver. - * - * The following major steps are followed for cleanup - - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from SDIO bus. - */ -static void -mwifiex_sdio_cleanup_module(void) -{ - struct mwifiex_adapter *adapter = g_adapter; - int i; - - if (down_interruptible(&add_remove_card_sem)) - goto exit_sem_err; - - if (!adapter || !adapter->priv_num) - goto exit; - - if (adapter->is_suspended) - mwifiex_sdio_resume(adapter->dev); - - for (i = 0; i < adapter->priv_num; i++) - if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) && - adapter->priv[i]->media_connected) - mwifiex_deauthenticate(adapter->priv[i], NULL); - - if (!adapter->surprise_removed) - mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY), - MWIFIEX_FUNC_SHUTDOWN); - -exit: - up(&add_remove_card_sem); - -exit_sem_err: - sdio_unregister_driver(&mwifiex_sdio); -} - -module_init(mwifiex_sdio_init_module); -module_exit(mwifiex_sdio_cleanup_module); - -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); -MODULE_VERSION(SDIO_VERSION); -MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE("sd8787.bin"); diff --git a/trunk/drivers/net/wireless/mwifiex/sdio.h b/trunk/drivers/net/wireless/mwifiex/sdio.h deleted file mode 100644 index a0e9bc5253e0..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sdio.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Marvell Wireless LAN device driver: SDIO specific definitions - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_SDIO_H -#define _MWIFIEX_SDIO_H - - -#include -#include -#include -#include - -#include "main.h" - -#define BLOCK_MODE 1 -#define BYTE_MODE 0 - -#define REG_PORT 0 -#define RD_BITMAP_L 0x04 -#define RD_BITMAP_U 0x05 -#define WR_BITMAP_L 0x06 -#define WR_BITMAP_U 0x07 -#define RD_LEN_P0_L 0x08 -#define RD_LEN_P0_U 0x09 - -#define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff - -#define MWIFIEX_SDIO_BYTE_MODE_MASK 0x80000000 - -#define CTRL_PORT 0 -#define CTRL_PORT_MASK 0x0001 -#define DATA_PORT_MASK 0xfffe - -#define MAX_MP_REGS 64 -#define MAX_PORT 16 - -#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8 - -#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (4096) /* 4K */ - -/* Multi port RX aggregation buffer size */ -#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (4096) /* 4K */ - -/* Misc. Config Register : Auto Re-enable interrupts */ -#define AUTO_RE_ENABLE_INT BIT(4) - -/* Host Control Registers */ -/* Host Control Registers : I/O port 0 */ -#define IO_PORT_0_REG 0x78 -/* Host Control Registers : I/O port 1 */ -#define IO_PORT_1_REG 0x79 -/* Host Control Registers : I/O port 2 */ -#define IO_PORT_2_REG 0x7A - -/* Host Control Registers : Configuration */ -#define CONFIGURATION_REG 0x00 -/* Host Control Registers : Host without Command 53 finish host*/ -#define HOST_TO_CARD_EVENT (0x1U << 3) -/* Host Control Registers : Host without Command 53 finish host */ -#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) -/* Host Control Registers : Host power up */ -#define HOST_POWER_UP (0x1U << 1) -/* Host Control Registers : Host power down */ -#define HOST_POWER_DOWN (0x1U << 0) - -/* Host Control Registers : Host interrupt mask */ -#define HOST_INT_MASK_REG 0x02 -/* Host Control Registers : Upload host interrupt mask */ -#define UP_LD_HOST_INT_MASK (0x1U) -/* Host Control Registers : Download host interrupt mask */ -#define DN_LD_HOST_INT_MASK (0x2U) -/* Enable Host interrupt mask */ -#define HOST_INT_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) -/* Disable Host interrupt mask */ -#define HOST_INT_DISABLE 0xff - -/* Host Control Registers : Host interrupt status */ -#define HOST_INTSTATUS_REG 0x03 -/* Host Control Registers : Upload host interrupt status */ -#define UP_LD_HOST_INT_STATUS (0x1U) -/* Host Control Registers : Download host interrupt status */ -#define DN_LD_HOST_INT_STATUS (0x2U) - -/* Host Control Registers : Host interrupt RSR */ -#define HOST_INT_RSR_REG 0x01 -/* Host Control Registers : Upload host interrupt RSR */ -#define UP_LD_HOST_INT_RSR (0x1U) -#define SDIO_INT_MASK 0x3F - -/* Host Control Registers : Host interrupt status */ -#define HOST_INT_STATUS_REG 0x28 -/* Host Control Registers : Upload CRC error */ -#define UP_LD_CRC_ERR (0x1U << 2) -/* Host Control Registers : Upload restart */ -#define UP_LD_RESTART (0x1U << 1) -/* Host Control Registers : Download restart */ -#define DN_LD_RESTART (0x1U << 0) - -/* Card Control Registers : Card status register */ -#define CARD_STATUS_REG 0x30 -/* Card Control Registers : Card I/O ready */ -#define CARD_IO_READY (0x1U << 3) -/* Card Control Registers : CIS card ready */ -#define CIS_CARD_RDY (0x1U << 2) -/* Card Control Registers : Upload card ready */ -#define UP_LD_CARD_RDY (0x1U << 1) -/* Card Control Registers : Download card ready */ -#define DN_LD_CARD_RDY (0x1U << 0) - -/* Card Control Registers : Host interrupt mask register */ -#define HOST_INTERRUPT_MASK_REG 0x34 -/* Card Control Registers : Host power interrupt mask */ -#define HOST_POWER_INT_MASK (0x1U << 3) -/* Card Control Registers : Abort card interrupt mask */ -#define ABORT_CARD_INT_MASK (0x1U << 2) -/* Card Control Registers : Upload card interrupt mask */ -#define UP_LD_CARD_INT_MASK (0x1U << 1) -/* Card Control Registers : Download card interrupt mask */ -#define DN_LD_CARD_INT_MASK (0x1U << 0) - -/* Card Control Registers : Card interrupt status register */ -#define CARD_INTERRUPT_STATUS_REG 0x38 -/* Card Control Registers : Power up interrupt */ -#define POWER_UP_INT (0x1U << 4) -/* Card Control Registers : Power down interrupt */ -#define POWER_DOWN_INT (0x1U << 3) - -/* Card Control Registers : Card interrupt RSR register */ -#define CARD_INTERRUPT_RSR_REG 0x3c -/* Card Control Registers : Power up RSR */ -#define POWER_UP_RSR (0x1U << 4) -/* Card Control Registers : Power down RSR */ -#define POWER_DOWN_RSR (0x1U << 3) - -/* Card Control Registers : Miscellaneous Configuration Register */ -#define CARD_MISC_CFG_REG 0x6C - -/* Host F1 read base 0 */ -#define HOST_F1_RD_BASE_0 0x0040 -/* Host F1 read base 1 */ -#define HOST_F1_RD_BASE_1 0x0041 -/* Host F1 card ready */ -#define HOST_F1_CARD_RDY 0x0020 - -/* Firmware status 0 register */ -#define CARD_FW_STATUS0_REG 0x60 -/* Firmware status 1 register */ -#define CARD_FW_STATUS1_REG 0x61 -/* Rx length register */ -#define CARD_RX_LEN_REG 0x62 -/* Rx unit register */ -#define CARD_RX_UNIT_REG 0x63 - -/* Event header Len*/ -#define MWIFIEX_EVENT_HEADER_LEN 8 - -/* Max retry number of CMD53 write */ -#define MAX_WRITE_IOMEM_RETRY 2 - -/* SDIO Tx aggregation in progress ? */ -#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0) - -/* SDIO Tx aggregation buffer room for next packet ? */ -#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len) \ - <= a->mpa_tx.buf_size) - -/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */ -#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do { \ - memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len], \ - payload, pkt_len); \ - a->mpa_tx.buf_len += pkt_len; \ - if (!a->mpa_tx.pkt_cnt) \ - a->mpa_tx.start_port = port; \ - if (a->mpa_tx.start_port <= port) \ - a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt)); \ - else \ - a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \ - a->mp_end_port))); \ - a->mpa_tx.pkt_cnt++; \ -} while (0); - -/* SDIO Tx aggregation limit ? */ -#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ - (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit) - -/* SDIO Tx aggregation port limit ? */ -#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \ - a->mpa_tx.start_port) && (((MAX_PORT - \ - a->mpa_tx.start_port) + a->curr_wr_port) >= \ - SDIO_MP_AGGR_DEF_PKT_LIMIT)) - -/* Reset SDIO Tx aggregation buffer parameters */ -#define MP_TX_AGGR_BUF_RESET(a) do { \ - a->mpa_tx.pkt_cnt = 0; \ - a->mpa_tx.buf_len = 0; \ - a->mpa_tx.ports = 0; \ - a->mpa_tx.start_port = 0; \ -} while (0); - -/* SDIO Rx aggregation limit ? */ -#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ - (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit) - -/* SDIO Tx aggregation port limit ? */ -#define MP_RX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_rd_port < \ - a->mpa_rx.start_port) && (((MAX_PORT - \ - a->mpa_rx.start_port) + a->curr_rd_port) >= \ - SDIO_MP_AGGR_DEF_PKT_LIMIT)) - -/* SDIO Rx aggregation in progress ? */ -#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0) - -/* SDIO Rx aggregation buffer room for next packet ? */ -#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) \ - ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size) - -/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ -#define MP_RX_AGGR_SETUP(a, skb, port) do { \ - a->mpa_rx.buf_len += skb->len; \ - if (!a->mpa_rx.pkt_cnt) \ - a->mpa_rx.start_port = port; \ - if (a->mpa_rx.start_port <= port) \ - a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt)); \ - else \ - a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt+1)); \ - a->mpa_rx.skb_arr[a->mpa_rx.pkt_cnt] = skb; \ - a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = skb->len; \ - a->mpa_rx.pkt_cnt++; \ -} while (0); - -/* Reset SDIO Rx aggregation buffer parameters */ -#define MP_RX_AGGR_BUF_RESET(a) do { \ - a->mpa_rx.pkt_cnt = 0; \ - a->mpa_rx.buf_len = 0; \ - a->mpa_rx.ports = 0; \ - a->mpa_rx.start_port = 0; \ -} while (0); - - -/* data structure for SDIO MPA TX */ -struct mwifiex_sdio_mpa_tx { - /* multiport tx aggregation buffer pointer */ - u8 *buf; - u32 buf_len; - u32 pkt_cnt; - u16 ports; - u16 start_port; - u8 enabled; - u32 buf_size; - u32 pkt_aggr_limit; -}; - -struct mwifiex_sdio_mpa_rx { - u8 *buf; - u32 buf_len; - u32 pkt_cnt; - u16 ports; - u16 start_port; - - struct sk_buff *skb_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; - u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; - - u8 enabled; - u32 buf_size; - u32 pkt_aggr_limit; -}; - -int mwifiex_bus_register(void); -void mwifiex_bus_unregister(void); - -struct sdio_mmc_card { - struct sdio_func *func; - struct mwifiex_adapter *adapter; - - u16 mp_rd_bitmap; - u16 mp_wr_bitmap; - - u16 mp_end_port; - u16 mp_data_port_mask; - - u8 curr_rd_port; - u8 curr_wr_port; - - u8 *mp_regs; - - struct mwifiex_sdio_mpa_tx mpa_tx; - struct mwifiex_sdio_mpa_rx mpa_rx; -}; -#endif /* _MWIFIEX_SDIO_H */ diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c deleted file mode 100644 index 33c8ba1f5e33..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station command handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * This function prepares command to set/get RSSI information. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting data/beacon average factors - * - Resetting SNR/NF/RSSI values in private structure - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 cmd_action) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + - S_DS_GEN); - cmd->params.rssi_info.action = cpu_to_le16(cmd_action); - cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor); - cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor); - - /* Reset SNR/NF/RSSI values in private structure */ - priv->data_rssi_last = 0; - priv->data_nf_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->bcn_rssi_last = 0; - priv->bcn_nf_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - - return 0; -} - -/* - * This function prepares command to set MAC control. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_mac_control(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; - u16 action = *((u16 *) data_buf); - - if (cmd_action != HostCmd_ACT_GEN_SET) { - dev_err(priv->adapter->dev, - "mac_control: only support set cmd\n"); - return -1; - } - - cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); - mac_ctrl->action = cpu_to_le16(action); - - return 0; -} - -/* - * This function prepares command to set/get SNMP MIB. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting SNMP MIB OID number and value - * (as required) - * - Ensuring correct endian-ness - * - * The following SNMP MIB OIDs are supported - - * - FRAG_THRESH_I : Fragmentation threshold - * - RTS_THRESH_I : RTS threshold - * - SHORT_RETRY_LIM_I : Short retry limit - * - DOT11D_I : 11d support - */ -static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u32 cmd_oid, - void *data_buf) -{ - struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; - u32 ul_temp; - - dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) - - 1 + S_DS_GEN); - - if (cmd_action == HostCmd_ACT_GEN_GET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); - snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + MAX_SNMP_BUF_SIZE); - } - - switch (cmd_oid) { - case FRAG_THRESH_I: - snmp_mib->oid = cpu_to_le16((u16) FRAG_THRESH_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - ul_temp = *((u32 *) data_buf); - *((__le16 *) (snmp_mib->value)) = - cpu_to_le16((u16) ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - case RTS_THRESH_I: - snmp_mib->oid = cpu_to_le16((u16) RTS_THRESH_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - ul_temp = *((u32 *) data_buf); - *(__le16 *) (snmp_mib->value) = - cpu_to_le16((u16) ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - - case SHORT_RETRY_LIM_I: - snmp_mib->oid = cpu_to_le16((u16) SHORT_RETRY_LIM_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - ul_temp = (*(u32 *) data_buf); - *((__le16 *) (snmp_mib->value)) = - cpu_to_le16((u16) ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - case DOT11D_I: - snmp_mib->oid = cpu_to_le16((u16) DOT11D_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - ul_temp = *(u32 *) data_buf; - *((__le16 *) (snmp_mib->value)) = - cpu_to_le16((u16) ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - default: - break; - } - dev_dbg(priv->adapter->dev, - "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x," - " Value=0x%x\n", - cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size), - le16_to_cpu(*(__le16 *) snmp_mib->value)); - return 0; -} - -/* - * This function prepares command to get log. - * - * Preparation includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + - S_DS_GEN); - return 0; -} - -/* - * This function prepares command to set/get Tx data rate configuration. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting configuration index, rate scope and rate drop pattern - * parameters (as required) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg; - struct mwifiex_rate_scope *rate_scope; - struct mwifiex_rate_drop_pattern *rate_drop; - u16 *pbitmap_rates = (u16 *) data_buf; - - u32 i; - - cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG); - - rate_cfg->action = cpu_to_le16(cmd_action); - rate_cfg->cfg_index = 0; - - rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg + - sizeof(struct host_cmd_ds_tx_rate_cfg)); - rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE); - rate_scope->length = cpu_to_le16(sizeof(struct mwifiex_rate_scope) - - sizeof(struct mwifiex_ie_types_header)); - if (pbitmap_rates != NULL) { - rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]); - rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]); - for (i = 0; - i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); - i++) - rate_scope->ht_mcs_rate_bitmap[i] = - cpu_to_le16(pbitmap_rates[2 + i]); - } else { - rate_scope->hr_dsss_rate_bitmap = - cpu_to_le16(priv->bitmap_rates[0]); - rate_scope->ofdm_rate_bitmap = - cpu_to_le16(priv->bitmap_rates[1]); - for (i = 0; - i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); - i++) - rate_scope->ht_mcs_rate_bitmap[i] = - cpu_to_le16(priv->bitmap_rates[2 + i]); - } - - rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + - sizeof(struct mwifiex_rate_scope)); - rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); - rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); - rate_drop->rate_drop_mode = 0; - - cmd->size = - cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + - sizeof(struct mwifiex_rate_scope) + - sizeof(struct mwifiex_rate_drop_pattern)); - - return 0; -} - -/* - * This function prepares command to set/get Tx power configuration. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting Tx power mode, power group TLV - * (as required) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct mwifiex_types_power_group *pg_tlv = NULL; - struct host_cmd_ds_txpwr_cfg *txp = NULL; - struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); - cmd->size = - cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); - switch (cmd_action) { - case HostCmd_ACT_GEN_SET: - txp = (struct host_cmd_ds_txpwr_cfg *) data_buf; - if (txp->mode) { - pg_tlv = (struct mwifiex_types_power_group - *) ((unsigned long) data_buf + - sizeof(struct host_cmd_ds_txpwr_cfg)); - memmove(cmd_txp_cfg, data_buf, - sizeof(struct host_cmd_ds_txpwr_cfg) + - sizeof(struct mwifiex_types_power_group) + - pg_tlv->length); - - pg_tlv = (struct mwifiex_types_power_group *) ((u8 *) - cmd_txp_cfg + - sizeof(struct host_cmd_ds_txpwr_cfg)); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + - sizeof(struct mwifiex_types_power_group) + - pg_tlv->length); - } else { - memmove(cmd_txp_cfg, data_buf, - sizeof(struct host_cmd_ds_txpwr_cfg)); - } - cmd_txp_cfg->action = cpu_to_le16(cmd_action); - break; - case HostCmd_ACT_GEN_GET: - cmd_txp_cfg->action = cpu_to_le16(cmd_action); - break; - } - - return 0; -} - -/* - * This function prepares command to set Host Sleep configuration. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting Host Sleep action, conditions, ARP filters - * (as required) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, - struct mwifiex_hs_config_param *data_buf) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; - u16 hs_activate = false; - - if (data_buf == NULL) - /* New Activate command */ - hs_activate = true; - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); - - if (!hs_activate && - (data_buf->conditions - != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) - && ((adapter->arp_filter_size > 0) - && (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { - dev_dbg(adapter->dev, - "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", - adapter->arp_filter_size); - memcpy(((u8 *) hs_cfg) + - sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), - adapter->arp_filter, adapter->arp_filter_size); - cmd->size = cpu_to_le16(adapter->arp_filter_size + - sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) - + S_DS_GEN); - } else { - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct - host_cmd_ds_802_11_hs_cfg_enh)); - } - if (hs_activate) { - hs_cfg->action = cpu_to_le16(HS_ACTIVATE); - hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED; - } else { - hs_cfg->action = cpu_to_le16(HS_CONFIGURE); - hs_cfg->params.hs_config.conditions = data_buf->conditions; - hs_cfg->params.hs_config.gpio = data_buf->gpio; - hs_cfg->params.hs_config.gap = data_buf->gap; - dev_dbg(adapter->dev, - "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", - hs_cfg->params.hs_config.conditions, - hs_cfg->params.hs_config.gpio, - hs_cfg->params.hs_config.gap); - } - - return 0; -} - -/* - * This function prepares command to set/get MAC address. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting MAC address (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + - S_DS_GEN); - cmd->result = 0; - - cmd->params.mac_addr.action = cpu_to_le16(cmd_action); - - if (cmd_action == HostCmd_ACT_GEN_SET) - memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, - ETH_ALEN); - return 0; -} - -/* - * This function prepares command to set MAC multicast address. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting MAC multicast address - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct mwifiex_multicast_list *mcast_list = - (struct mwifiex_multicast_list *) data_buf; - struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr; - - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + - S_DS_GEN); - cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR); - - mcast_addr->action = cpu_to_le16(cmd_action); - mcast_addr->num_of_adrs = - cpu_to_le16((u16) mcast_list->num_multicast_addr); - memcpy(mcast_addr->mac_list, mcast_list->mac_list, - mcast_list->num_multicast_addr * ETH_ALEN); - - return 0; -} - -/* - * This function prepares command to deauthenticate. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting AP MAC address and reason code - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) -{ - struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) - + S_DS_GEN); - - /* Set AP MAC address */ - memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN); - - dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr); - - deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); - - return 0; -} - -/* - * This function prepares command to stop Ad-Hoc network. - * - * Preparation includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP); - cmd->size = cpu_to_le16(S_DS_GEN); - return 0; -} - -/* - * This function sets WEP key(s) to key parameter TLV(s). - * - * Multi-key parameter TLVs are supported, so we can send multiple - * WEP keys in a single buffer. - */ -static int -mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, - struct mwifiex_ie_type_key_param_set *key_param_set, - u16 *key_param_len) -{ - int cur_key_param_len = 0; - u8 i; - - /* Multi-key_param_set TLV is supported */ - for (i = 0; i < NUM_WEP_KEYS; i++) { - if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) || - (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) { - key_param_set->type = - cpu_to_le16(TLV_TYPE_KEY_MATERIAL); -/* Key_param_set WEP fixed length */ -#define KEYPARAMSET_WEP_FIXED_LEN 8 - key_param_set->length = cpu_to_le16((u16) - (priv->wep_key[i]. - key_length + - KEYPARAMSET_WEP_FIXED_LEN)); - key_param_set->key_type_id = - cpu_to_le16(KEY_TYPE_ID_WEP); - key_param_set->key_info = - cpu_to_le16(KEY_ENABLED | KEY_UNICAST | - KEY_MCAST); - key_param_set->key_len = - cpu_to_le16(priv->wep_key[i].key_length); - /* Set WEP key index */ - key_param_set->key[0] = i; - /* Set default Tx key flag */ - if (i == - (priv-> - wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK)) - key_param_set->key[1] = 1; - else - key_param_set->key[1] = 0; - memmove(&key_param_set->key[2], - priv->wep_key[i].key_material, - priv->wep_key[i].key_length); - - cur_key_param_len = priv->wep_key[i].key_length + - KEYPARAMSET_WEP_FIXED_LEN + - sizeof(struct mwifiex_ie_types_header); - *key_param_len += (u16) cur_key_param_len; - key_param_set = - (struct mwifiex_ie_type_key_param_set *) - ((u8 *)key_param_set + - cur_key_param_len); - } else if (!priv->wep_key[i].key_length) { - continue; - } else { - dev_err(priv->adapter->dev, - "key%d Length = %d is incorrect\n", - (i + 1), priv->wep_key[i].key_length); - return -1; - } - } - - return 0; -} - -/* - * This function prepares command to set/get/reset network key(s). - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting WEP keys, WAPI keys or WPA keys along with required - * encryption (TKIP, AES) (as required) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, - u32 cmd_oid, void *data_buf) -{ - struct host_cmd_ds_802_11_key_material *key_material = - &cmd->params.key_material; - struct mwifiex_ds_encrypt_key *enc_key = - (struct mwifiex_ds_encrypt_key *) data_buf; - u16 key_param_len = 0; - int ret = 0; - const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); - key_material->action = cpu_to_le16(cmd_action); - - if (cmd_action == HostCmd_ACT_GEN_GET) { - cmd->size = - cpu_to_le16(sizeof(key_material->action) + S_DS_GEN); - return ret; - } - - if (!enc_key) { - memset(&key_material->key_param_set, 0, - (NUM_WEP_KEYS * - sizeof(struct mwifiex_ie_type_key_param_set))); - ret = mwifiex_set_keyparamset_wep(priv, - &key_material->key_param_set, - &key_param_len); - cmd->size = cpu_to_le16(key_param_len + - sizeof(key_material->action) + S_DS_GEN); - return ret; - } else - memset(&key_material->key_param_set, 0, - sizeof(struct mwifiex_ie_type_key_param_set)); - if (enc_key->is_wapi_key) { - dev_dbg(priv->adapter->dev, "info: Set WAPI Key\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_WAPI); - if (cmd_oid == KEY_INFO_ENABLED) - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - else - key_material->key_param_set.key_info = - cpu_to_le16(!KEY_ENABLED); - - key_material->key_param_set.key[0] = enc_key->key_index; - if (!priv->sec_info.wapi_key_on) - key_material->key_param_set.key[1] = 1; - else - /* set 0 when re-key */ - key_material->key_param_set.key[1] = 0; - - if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) { - /* WAPI pairwise key: unicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_UNICAST); - } else { /* WAPI group key: multicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_MCAST); - priv->sec_info.wapi_key_on = true; - } - - key_material->key_param_set.type = - cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - key_material->key_param_set.key_len = - cpu_to_le16(WAPI_KEY_LEN); - memcpy(&key_material->key_param_set.key[2], - enc_key->key_material, enc_key->key_len); - memcpy(&key_material->key_param_set.key[2 + enc_key->key_len], - enc_key->wapi_rxpn, WAPI_RXPN_LEN); - key_material->key_param_set.length = - cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); - - key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + - sizeof(struct mwifiex_ie_types_header); - cmd->size = cpu_to_le16(key_param_len + - sizeof(key_material->action) + S_DS_GEN); - return ret; - } - if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { - dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_AES); - if (cmd_oid == KEY_INFO_ENABLED) - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - else - key_material->key_param_set.key_info = - cpu_to_le16(!KEY_ENABLED); - - if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) - /* AES pairwise key: unicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_UNICAST); - else /* AES group key: multicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_MCAST); - } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { - dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_TKIP); - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - - if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) - /* TKIP pairwise key: unicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_UNICAST); - else /* TKIP group key: multicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_MCAST); - } - - if (key_material->key_param_set.key_type_id) { - key_material->key_param_set.type = - cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - key_material->key_param_set.key_len = - cpu_to_le16((u16) enc_key->key_len); - memcpy(key_material->key_param_set.key, enc_key->key_material, - enc_key->key_len); - key_material->key_param_set.length = - cpu_to_le16((u16) enc_key->key_len + - KEYPARAMSET_FIXED_LEN); - - key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN) - + sizeof(struct mwifiex_ie_types_header); - - cmd->size = cpu_to_le16(key_param_len + - sizeof(key_material->action) + S_DS_GEN); - } - - return ret; -} - -/* - * This function prepares command to set/get 11d domain information. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting domain information fields (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11d_domain_info *domain_info = - &cmd->params.domain_info; - struct mwifiex_ietypes_domain_param_set *domain = - &domain_info->domain; - u8 no_of_triplet = adapter->domain_reg.no_of_triplet; - - dev_dbg(adapter->dev, "info: 11D: no_of_triplet=0x%x\n", no_of_triplet); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO); - domain_info->action = cpu_to_le16(cmd_action); - if (cmd_action == HostCmd_ACT_GEN_GET) { - cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); - return 0; - } - - /* Set domain info fields */ - domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY); - memcpy(domain->country_code, adapter->domain_reg.country_code, - sizeof(domain->country_code)); - - domain->header.len = cpu_to_le16((no_of_triplet * - sizeof(struct ieee80211_country_ie_triplet)) + - sizeof(domain->country_code)); - - if (no_of_triplet) { - memcpy(domain->triplet, adapter->domain_reg.triplet, - no_of_triplet * - sizeof(struct ieee80211_country_ie_triplet)); - - cmd->size = cpu_to_le16(sizeof(domain_info->action) + - le16_to_cpu(domain->header.len) + - sizeof(struct mwifiex_ie_types_header) - + S_DS_GEN); - } else { - cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); - } - - return 0; -} - -/* - * This function prepares command to set/get RF channel. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting RF type and current RF channel (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_802_11_rf_channel *rf_chan = - &cmd->params.rf_channel; - uint16_t rf_type = le16_to_cpu(rf_chan->rf_type); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rf_channel) - + S_DS_GEN); - - if (cmd_action == HostCmd_ACT_GEN_SET) { - if ((priv->adapter->adhoc_start_band & BAND_A) - || (priv->adapter->adhoc_start_band & BAND_AN)) - rf_chan->rf_type = - cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A); - - rf_type = le16_to_cpu(rf_chan->rf_type); - SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset); - rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf)); - } - rf_chan->action = cpu_to_le16(cmd_action); - return 0; -} - -/* - * This function prepares command to set/get IBSS coalescing status. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting status to enable or disable (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_802_11_ibss_status *ibss_coal = - &(cmd->params.ibss_coalescing); - u16 enable = 0; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) + - S_DS_GEN); - cmd->result = 0; - ibss_coal->action = cpu_to_le16(cmd_action); - - switch (cmd_action) { - case HostCmd_ACT_GEN_SET: - if (data_buf != NULL) - enable = *(u16 *) data_buf; - ibss_coal->enable = cpu_to_le16(enable); - break; - - /* In other case.. Nothing to do */ - case HostCmd_ACT_GEN_GET: - default: - break; - } - - return 0; -} - -/* - * This function prepares command to set/get register value. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting register offset (for both GET and SET) and - * register value (for SET only) - * - Ensuring correct endian-ness - * - * The following type of registers can be accessed with this function - - * - MAC register - * - BBP register - * - RF register - * - PMIC register - * - CAU register - * - EEPROM - */ -static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct mwifiex_ds_reg_rw *reg_rw; - - reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; - switch (le16_to_cpu(cmd->command)) { - case HostCmd_CMD_MAC_REG_ACCESS: - { - struct host_cmd_ds_mac_reg_access *mac_reg; - - cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); - mac_reg = (struct host_cmd_ds_mac_reg_access *) &cmd-> - params.mac_reg; - mac_reg->action = cpu_to_le16(cmd_action); - mac_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - mac_reg->value = reg_rw->value; - break; - } - case HostCmd_CMD_BBP_REG_ACCESS: - { - struct host_cmd_ds_bbp_reg_access *bbp_reg; - - cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); - bbp_reg = (struct host_cmd_ds_bbp_reg_access *) &cmd-> - params.bbp_reg; - bbp_reg->action = cpu_to_le16(cmd_action); - bbp_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - bbp_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_RF_REG_ACCESS: - { - struct host_cmd_ds_rf_reg_access *rf_reg; - - cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); - rf_reg = (struct host_cmd_ds_rf_reg_access *) &cmd-> - params.rf_reg; - rf_reg->action = cpu_to_le16(cmd_action); - rf_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - rf_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_PMIC_REG_ACCESS: - { - struct host_cmd_ds_pmic_reg_access *pmic_reg; - - cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); - pmic_reg = (struct host_cmd_ds_pmic_reg_access *) &cmd-> - params.pmic_reg; - pmic_reg->action = cpu_to_le16(cmd_action); - pmic_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - pmic_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_CAU_REG_ACCESS: - { - struct host_cmd_ds_rf_reg_access *cau_reg; - - cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); - cau_reg = (struct host_cmd_ds_rf_reg_access *) &cmd-> - params.rf_reg; - cau_reg->action = cpu_to_le16(cmd_action); - cau_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - cau_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_802_11_EEPROM_ACCESS: - { - struct mwifiex_ds_read_eeprom *rd_eeprom = - (struct mwifiex_ds_read_eeprom *) data_buf; - struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom = - (struct host_cmd_ds_802_11_eeprom_access *) - &cmd->params.eeprom; - - cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); - cmd_eeprom->action = cpu_to_le16(cmd_action); - cmd_eeprom->offset = rd_eeprom->offset; - cmd_eeprom->byte_count = rd_eeprom->byte_count; - cmd_eeprom->value = 0; - break; - } - default: - return -1; - } - - return 0; -} - -/* - * This function prepares the commands before sending them to the firmware. - * - * This is a generic function which calls specific command preparation - * routines based upon the command number. - */ -int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *data_buf, void *cmd_buf) -{ - struct host_cmd_ds_command *cmd_ptr = - (struct host_cmd_ds_command *) cmd_buf; - int ret = 0; - - /* Prepare command */ - switch (cmd_no) { - case HostCmd_CMD_GET_HW_SPEC: - ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); - break; - case HostCmd_CMD_MAC_CONTROL: - ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_802_11_MAC_ADDRESS: - ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr, - cmd_action); - break; - case HostCmd_CMD_MAC_MULTICAST_ADR: - ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_TX_RATE_CFG: - ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_TXPWR_CFG: - ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_802_11_PS_MODE_ENH: - ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, - (uint16_t)cmd_oid, data_buf); - break; - case HostCmd_CMD_802_11_HS_CFG_ENH: - ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action, - (struct mwifiex_hs_config_param *) data_buf); - break; - case HostCmd_CMD_802_11_SCAN: - ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf); - break; - case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr); - break; - case HostCmd_CMD_802_11_ASSOCIATE: - ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_802_11_DEAUTHENTICATE: - ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_802_11_AD_HOC_START: - ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_802_11_GET_LOG: - ret = mwifiex_cmd_802_11_get_log(cmd_ptr); - break; - case HostCmd_CMD_802_11_AD_HOC_JOIN: - ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_802_11_AD_HOC_STOP: - ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr); - break; - case HostCmd_CMD_RSSI_INFO: - ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); - break; - case HostCmd_CMD_802_11_SNMP_MIB: - ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action, - cmd_oid, data_buf); - break; - case HostCmd_CMD_802_11_TX_RATE_QUERY: - cmd_ptr->command = - cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + - S_DS_GEN); - priv->tx_rate = 0; - ret = 0; - break; - case HostCmd_CMD_VERSION_EXT: - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->params.verext.version_str_sel = - (u8) (*((u32 *) data_buf)); - memcpy(&cmd_ptr->params, data_buf, - sizeof(struct host_cmd_ds_version_ext)); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + - S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_802_11_RF_CHANNEL: - ret = mwifiex_cmd_802_11_rf_channel(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_FUNC_INIT: - if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) - priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->size = cpu_to_le16(S_DS_GEN); - break; - case HostCmd_CMD_FUNC_SHUTDOWN: - priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET; - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->size = cpu_to_le16(S_DS_GEN); - break; - case HostCmd_CMD_11N_ADDBA_REQ: - ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf); - break; - case HostCmd_CMD_11N_DELBA: - ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf); - break; - case HostCmd_CMD_11N_ADDBA_RSP: - ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_802_11_KEY_MATERIAL: - ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr, - cmd_action, cmd_oid, - data_buf); - break; - case HostCmd_CMD_802_11D_DOMAIN_INFO: - ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr, - cmd_action); - break; - case HostCmd_CMD_RECONFIGURE_TX_BUFF: - ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_AMSDU_AGGR_CTRL: - ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_11N_CFG: - ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_WMM_GET_STATUS: - dev_dbg(priv->adapter->dev, - "cmd: WMM: WMM_GET_STATUS cmd sent\n"); - cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + - S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: - ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_MAC_REG_ACCESS: - case HostCmd_CMD_BBP_REG_ACCESS: - case HostCmd_CMD_RF_REG_ACCESS: - case HostCmd_CMD_PMIC_REG_ACCESS: - case HostCmd_CMD_CAU_REG_ACCESS: - case HostCmd_CMD_802_11_EEPROM_ACCESS: - ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf); - break; - case HostCmd_CMD_SET_BSS_MODE: - cmd_ptr->command = cpu_to_le16(cmd_no); - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) - cmd_ptr->params.bss_mode.con_type = - CONNECTION_TYPE_ADHOC; - else if (priv->bss_mode == NL80211_IFTYPE_STATION) - cmd_ptr->params.bss_mode.con_type = - CONNECTION_TYPE_INFRA; - cmd_ptr->size = cpu_to_le16(sizeof(struct - host_cmd_ds_set_bss_mode) + S_DS_GEN); - ret = 0; - break; - default: - dev_err(priv->adapter->dev, - "PREP_CMD: unknown cmd- %#x\n", cmd_no); - ret = -1; - break; - } - return ret; -} - -/* - * This function issues commands to initialize firmware. - * - * This is called after firmware download to bring the card to - * working state. - * - * The following commands are issued sequentially - - * - Function init (for first interface only) - * - Read MAC address (for first interface only) - * - Reconfigure Tx buffer size (for first interface only) - * - Enable auto deep sleep (for first interface only) - * - Get Tx rate - * - Get Tx power - * - Set IBSS coalescing status - * - Set AMSDU aggregation control - * - Set 11d control - * - Set MAC control (this must be the last command to initialize firmware) - */ -int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) -{ - int ret = 0; - u16 enable = true; - struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; - struct mwifiex_ds_auto_ds auto_ds; - enum state_11d_t state_11d; - - if (first_sta) { - - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, - HostCmd_ACT_GEN_SET, 0, NULL); - if (ret) - return -1; - /* Read MAC address from HW */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_GET_HW_SPEC, - HostCmd_ACT_GEN_GET, 0, NULL); - if (ret) - return -1; - - /* Reconfigure tx buf size */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, - &priv->adapter->tx_buf_size); - if (ret) - return -1; - - /* Enable IEEE PS by default */ - priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_STA_PS, NULL); - if (ret) - return -1; - } - - /* get tx rate */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_GET, 0, NULL); - if (ret) - return -1; - priv->data_rate = 0; - - /* get tx power */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG, - HostCmd_ACT_GEN_GET, 0, NULL); - if (ret) - return -1; - - /* set ibss coalescing_status */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, - HostCmd_ACT_GEN_SET, 0, &enable); - if (ret) - return -1; - - memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); - amsdu_aggr_ctrl.enable = true; - /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, - HostCmd_ACT_GEN_SET, 0, - (void *) &amsdu_aggr_ctrl); - if (ret) - return -1; - /* MAC Control must be the last command in init_fw */ - /* set MAC Control */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter); - if (ret) - return -1; - - if (first_sta) { - /* Enable auto deep sleep */ - auto_ds.auto_ds = DEEP_SLEEP_ON; - auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_AUTO_DS, - &auto_ds); - if (ret) - return -1; - } - - /* Send cmd to FW to enable/disable 11D function */ - state_11d = ENABLE_11D; - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d); - if (ret) - dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); - - /* set last_init_cmd */ - priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB; - ret = -EINPROGRESS; - - return ret; -} diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c deleted file mode 100644 index 7f4f10b752fb..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ /dev/null @@ -1,972 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station command response handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - - -/* - * This function handles the command response error case. - * - * For scan response error, the function cancels all the pending - * scan commands and generates an event to inform the applications - * of the scan completion. - * - * For Power Save command failure, we do not retry enter PS - * command in case of Ad-hoc mode. - * - * For all other response errors, the current command buffer is freed - * and returned to the free command queue. - */ -static void -mwifiex_process_cmdresp_error(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ps_mode_enh *pm; - unsigned long flags; - - dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n", - resp->command, resp->result); - - if (adapter->curr_cmd->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - - switch (le16_to_cpu(resp->command)) { - case HostCmd_CMD_802_11_PS_MODE_ENH: - pm = &resp->params.psmode_enh; - dev_err(adapter->dev, "PS_MODE_ENH cmd failed: " - "result=0x%x action=0x%X\n", - resp->result, le16_to_cpu(pm->action)); - /* We do not re-try enter-ps command in ad-hoc mode. */ - if (le16_to_cpu(pm->action) == EN_AUTO_PS && - (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) && - priv->bss_mode == NL80211_IFTYPE_ADHOC) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - - break; - case HostCmd_CMD_802_11_SCAN: - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - if (priv->report_scan_result) - priv->report_scan_result = false; - if (priv->scan_pending_on_block) { - priv->scan_pending_on_block = false; - up(&priv->async_sem); - } - break; - - case HostCmd_CMD_MAC_CONTROL: - break; - - default: - break; - } - /* Handling errors here */ - mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -} - -/* - * This function handles the command response of get RSSI info. - * - * Handling includes changing the header fields into CPU format - * and saving the following parameters in driver - - * - Last data and beacon RSSI value - * - Average data and beacon RSSI value - * - Last data and beacon NF value - * - Average data and beacon NF value - * - * The parameters are send to the application as well, along with - * calculated SNR values. - */ -static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = - &resp->params.rssi_info_rsp; - struct mwifiex_ds_get_signal *signal = NULL; - - priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); - priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); - - priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); - priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); - - priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); - priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); - - priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); - priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); - - /* Need to indicate IOCTL complete */ - if (data_buf) { - signal = (struct mwifiex_ds_get_signal *) data_buf; - memset(signal, 0, sizeof(struct mwifiex_ds_get_signal)); - - signal->selector = ALL_RSSI_INFO_MASK; - - /* RSSI */ - signal->bcn_rssi_last = priv->bcn_rssi_last; - signal->bcn_rssi_avg = priv->bcn_rssi_avg; - signal->data_rssi_last = priv->data_rssi_last; - signal->data_rssi_avg = priv->data_rssi_avg; - - /* SNR */ - signal->bcn_snr_last = - CAL_SNR(priv->bcn_rssi_last, priv->bcn_nf_last); - signal->bcn_snr_avg = - CAL_SNR(priv->bcn_rssi_avg, priv->bcn_nf_avg); - signal->data_snr_last = - CAL_SNR(priv->data_rssi_last, priv->data_nf_last); - signal->data_snr_avg = - CAL_SNR(priv->data_rssi_avg, priv->data_nf_avg); - - /* NF */ - signal->bcn_nf_last = priv->bcn_nf_last; - signal->bcn_nf_avg = priv->bcn_nf_avg; - signal->data_nf_last = priv->data_nf_last; - signal->data_nf_avg = priv->data_nf_avg; - } - - return 0; -} - -/* - * This function handles the command response of set/get SNMP - * MIB parameters. - * - * Handling includes changing the header fields into CPU format - * and saving the parameter in driver. - * - * The following parameters are supported - - * - Fragmentation threshold - * - RTS threshold - * - Short retry limit - */ -static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; - u16 oid = le16_to_cpu(smib->oid); - u16 query_type = le16_to_cpu(smib->query_type); - u32 ul_temp; - - dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x," - " query_type = %#x, buf size = %#x\n", - oid, query_type, le16_to_cpu(smib->buf_size)); - if (query_type == HostCmd_ACT_GEN_GET) { - ul_temp = le16_to_cpu(*((__le16 *) (smib->value))); - if (data_buf) - *(u32 *)data_buf = ul_temp; - switch (oid) { - case FRAG_THRESH_I: - dev_dbg(priv->adapter->dev, - "info: SNMP_RESP: FragThsd =%u\n", ul_temp); - break; - case RTS_THRESH_I: - dev_dbg(priv->adapter->dev, - "info: SNMP_RESP: RTSThsd =%u\n", ul_temp); - break; - case SHORT_RETRY_LIM_I: - dev_dbg(priv->adapter->dev, - "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); - break; - default: - break; - } - } - - return 0; -} - -/* - * This function handles the command response of get log request - * - * Handling includes changing the header fields into CPU format - * and sending the received parameters to application. - */ -static int mwifiex_ret_get_log(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_802_11_get_log *get_log = - (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; - struct mwifiex_ds_get_stats *stats = NULL; - - if (data_buf) { - stats = (struct mwifiex_ds_get_stats *) data_buf; - stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); - stats->failed = le32_to_cpu(get_log->failed); - stats->retry = le32_to_cpu(get_log->retry); - stats->multi_retry = le32_to_cpu(get_log->multi_retry); - stats->frame_dup = le32_to_cpu(get_log->frame_dup); - stats->rts_success = le32_to_cpu(get_log->rts_success); - stats->rts_failure = le32_to_cpu(get_log->rts_failure); - stats->ack_failure = le32_to_cpu(get_log->ack_failure); - stats->rx_frag = le32_to_cpu(get_log->rx_frag); - stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); - stats->fcs_error = le32_to_cpu(get_log->fcs_error); - stats->tx_frame = le32_to_cpu(get_log->tx_frame); - stats->wep_icv_error[0] = - le32_to_cpu(get_log->wep_icv_err_cnt[0]); - stats->wep_icv_error[1] = - le32_to_cpu(get_log->wep_icv_err_cnt[1]); - stats->wep_icv_error[2] = - le32_to_cpu(get_log->wep_icv_err_cnt[2]); - stats->wep_icv_error[3] = - le32_to_cpu(get_log->wep_icv_err_cnt[3]); - } - - return 0; -} - -/* - * This function handles the command response of set/get Tx rate - * configurations. - * - * Handling includes changing the header fields into CPU format - * and saving the following parameters in driver - - * - DSSS rate bitmap - * - OFDM rate bitmap - * - HT MCS rate bitmaps - * - * Based on the new rate bitmaps, the function re-evaluates if - * auto data rate has been activated. If not, it sends another - * query to the firmware to get the current Tx data rate and updates - * the driver value. - */ -static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct mwifiex_rate_cfg *ds_rate = NULL; - struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; - struct mwifiex_rate_scope *rate_scope; - struct mwifiex_ie_types_header *head = NULL; - u16 tlv, tlv_buf_len; - u8 *tlv_buf; - u32 i; - int ret = 0; - - tlv_buf = (u8 *) ((u8 *) rate_cfg) + - sizeof(struct host_cmd_ds_tx_rate_cfg); - tlv_buf_len = *(u16 *) (tlv_buf + sizeof(u16)); - - while (tlv_buf && tlv_buf_len > 0) { - tlv = (*tlv_buf); - tlv = tlv | (*(tlv_buf + 1) << 8); - - switch (tlv) { - case TLV_TYPE_RATE_SCOPE: - rate_scope = (struct mwifiex_rate_scope *) tlv_buf; - priv->bitmap_rates[0] = - le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); - priv->bitmap_rates[1] = - le16_to_cpu(rate_scope->ofdm_rate_bitmap); - for (i = 0; - i < - sizeof(rate_scope->ht_mcs_rate_bitmap) / - sizeof(u16); i++) - priv->bitmap_rates[2 + i] = - le16_to_cpu(rate_scope-> - ht_mcs_rate_bitmap[i]); - break; - /* Add RATE_DROP tlv here */ - } - - head = (struct mwifiex_ie_types_header *) tlv_buf; - tlv_buf += le16_to_cpu(head->len) + sizeof(*head); - tlv_buf_len -= le16_to_cpu(head->len); - } - - priv->is_data_rate_auto = mwifiex_is_rate_auto(priv); - - if (priv->is_data_rate_auto) - priv->data_rate = 0; - else - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL); - - if (data_buf) { - ds_rate = (struct mwifiex_rate_cfg *) data_buf; - if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) { - if (priv->is_data_rate_auto) { - ds_rate->is_rate_auto = 1; - } else { - ds_rate->rate = mwifiex_get_rate_index(priv-> - bitmap_rates, - sizeof(priv-> - bitmap_rates)); - if (ds_rate->rate >= - MWIFIEX_RATE_BITMAP_OFDM0 - && ds_rate->rate <= - MWIFIEX_RATE_BITMAP_OFDM7) - ds_rate->rate -= - (MWIFIEX_RATE_BITMAP_OFDM0 - - MWIFIEX_RATE_INDEX_OFDM0); - if (ds_rate->rate >= - MWIFIEX_RATE_BITMAP_MCS0 - && ds_rate->rate <= - MWIFIEX_RATE_BITMAP_MCS127) - ds_rate->rate -= - (MWIFIEX_RATE_BITMAP_MCS0 - - MWIFIEX_RATE_INDEX_MCS0); - } - } - } - - return ret; -} - -/* - * This function handles the command response of get Tx power level. - * - * Handling includes saving the maximum and minimum Tx power levels - * in driver, as well as sending the values to user. - */ -static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) -{ - int length = -1, max_power = -1, min_power = -1; - struct mwifiex_types_power_group *pg_tlv_hdr = NULL; - struct mwifiex_power_group *pg = NULL; - - if (data_buf) { - pg_tlv_hdr = - (struct mwifiex_types_power_group *) ((u8 *) data_buf - + sizeof(struct host_cmd_ds_txpwr_cfg)); - pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr + - sizeof(struct mwifiex_types_power_group)); - length = pg_tlv_hdr->length; - if (length > 0) { - max_power = pg->power_max; - min_power = pg->power_min; - length -= sizeof(struct mwifiex_power_group); - } - while (length) { - pg++; - if (max_power < pg->power_max) - max_power = pg->power_max; - - if (min_power > pg->power_min) - min_power = pg->power_min; - - length -= sizeof(struct mwifiex_power_group); - } - if (pg_tlv_hdr->length > 0) { - priv->min_tx_power_level = (u8) min_power; - priv->max_tx_power_level = (u8) max_power; - } - } else { - return -1; - } - - return 0; -} - -/* - * This function handles the command response of set/get Tx power - * configurations. - * - * Handling includes changing the header fields into CPU format - * and saving the current Tx power level in driver. - */ -static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; - struct mwifiex_types_power_group *pg_tlv_hdr = NULL; - struct mwifiex_power_group *pg = NULL; - u16 action = le16_to_cpu(txp_cfg->action); - - switch (action) { - case HostCmd_ACT_GEN_GET: - { - pg_tlv_hdr = - (struct mwifiex_types_power_group *) ((u8 *) - txp_cfg + - sizeof - (struct - host_cmd_ds_txpwr_cfg)); - pg = (struct mwifiex_power_group *) ((u8 *) - pg_tlv_hdr + - sizeof(struct - mwifiex_types_power_group)); - if (adapter->hw_status == - MWIFIEX_HW_STATUS_INITIALIZING) - mwifiex_get_power_level(priv, txp_cfg); - priv->tx_power_level = (u16) pg->power_min; - break; - } - case HostCmd_ACT_GEN_SET: - if (le32_to_cpu(txp_cfg->mode)) { - pg_tlv_hdr = - (struct mwifiex_types_power_group *) ((u8 *) - txp_cfg + - sizeof - (struct - host_cmd_ds_txpwr_cfg)); - pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr - + - sizeof(struct - mwifiex_types_power_group)); - if (pg->power_max == pg->power_min) - priv->tx_power_level = (u16) pg->power_min; - } - break; - default: - dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n", - action); - return 0; - } - dev_dbg(adapter->dev, - "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", - priv->tx_power_level, priv->max_tx_power_level, - priv->min_tx_power_level); - - return 0; -} - -/* - * This function handles the command response of set/get MAC address. - * - * Handling includes saving the MAC address in driver. - */ -static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_mac_address *cmd_mac_addr = - &resp->params.mac_addr; - - memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); - - dev_dbg(priv->adapter->dev, - "info: set mac address: %pM\n", priv->curr_addr); - - return 0; -} - -/* - * This function handles the command response of set/get MAC multicast - * address. - */ -static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - return 0; -} - -/* - * This function handles the command response of get Tx rate query. - * - * Handling includes changing the header fields into CPU format - * and saving the Tx rate and HT information parameters in driver. - * - * Both rate configuration and current data rate can be retrieved - * with this request. - */ -static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - priv->tx_rate = resp->params.tx_rate.tx_rate; - priv->tx_htinfo = resp->params.tx_rate.ht_info; - if (!priv->is_data_rate_auto) - priv->data_rate = - mwifiex_index_to_data_rate(priv->tx_rate, - priv->tx_htinfo); - - return 0; -} - -/* - * This function handles the command response of a deauthenticate - * command. - * - * If the deauthenticated MAC matches the current BSS MAC, the connection - * state is reset. - */ -static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - adapter->dbg.num_cmd_deauth++; - if (!memcmp(resp->params.deauth.mac_addr, - &priv->curr_bss_params.bss_descriptor.mac_address, - sizeof(resp->params.deauth.mac_addr))) - mwifiex_reset_connect_state(priv); - - return 0; -} - -/* - * This function handles the command response of ad-hoc stop. - * - * The function resets the connection state in driver. - */ -static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - mwifiex_reset_connect_state(priv); - return 0; -} - -/* - * This function handles the command response of set/get key material. - * - * Handling includes updating the driver parameters to reflect the - * changes. - */ -static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_key_material *key = - &resp->params.key_material; - - if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { - if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { - dev_dbg(priv->adapter->dev, "info: key: GTK is set\n"); - priv->wpa_is_gtk_set = true; - priv->scan_block = false; - } - } - - memset(priv->aes_key.key_param_set.key, 0, - sizeof(key->key_param_set.key)); - priv->aes_key.key_param_set.key_len = key->key_param_set.key_len; - memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, - le16_to_cpu(priv->aes_key.key_param_set.key_len)); - - return 0; -} - -/* - * This function handles the command response of get 11d domain information. - */ -static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = - &resp->params.domain_info_resp; - struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; - u16 action = le16_to_cpu(domain_info->action); - u8 no_of_triplet = 0; - - no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - - IEEE80211_COUNTRY_STRING_LEN) / - sizeof(struct ieee80211_country_ie_triplet)); - - dev_dbg(priv->adapter->dev, "info: 11D Domain Info Resp:" - " no_of_triplet=%d\n", no_of_triplet); - - if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) { - dev_warn(priv->adapter->dev, - "11D: invalid number of triplets %d " - "returned!!\n", no_of_triplet); - return -1; - } - - switch (action) { - case HostCmd_ACT_GEN_SET: /* Proc Set Action */ - break; - case HostCmd_ACT_GEN_GET: - break; - default: - dev_err(priv->adapter->dev, - "11D: invalid action:%d\n", domain_info->action); - return -1; - } - - return 0; -} - -/* - * This function handles the command response of get RF channel. - * - * Handling includes changing the header fields into CPU format - * and saving the new channel in driver. - */ -static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_802_11_rf_channel *rf_channel = - &resp->params.rf_channel; - u16 new_channel = le16_to_cpu(rf_channel->current_channel); - - if (priv->curr_bss_params.bss_descriptor.channel != new_channel) { - dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n", - priv->curr_bss_params.bss_descriptor.channel, - new_channel); - /* Update the channel again */ - priv->curr_bss_params.bss_descriptor.channel = new_channel; - } - if (data_buf) - *((u16 *)data_buf) = new_channel; - - return 0; -} - -/* - * This function handles the command response of get extended version. - * - * Handling includes forming the extended version string and sending it - * to application. - */ -static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; - struct host_cmd_ds_version_ext *version_ext = NULL; - - if (data_buf) { - version_ext = (struct host_cmd_ds_version_ext *)data_buf; - version_ext->version_str_sel = ver_ext->version_str_sel; - memcpy(version_ext->version_str, ver_ext->version_str, - sizeof(char) * 128); - memcpy(priv->version_str, ver_ext->version_str, 128); - } - return 0; -} - -/* - * This function handles the command response of register access. - * - * The register value and offset are returned to the user. For EEPROM - * access, the byte count is also returned. - */ -static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct mwifiex_ds_reg_rw *reg_rw = NULL; - struct mwifiex_ds_read_eeprom *eeprom = NULL; - - if (data_buf) { - reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; - eeprom = (struct mwifiex_ds_read_eeprom *) data_buf; - switch (type) { - case HostCmd_CMD_MAC_REG_ACCESS: - { - struct host_cmd_ds_mac_reg_access *reg; - reg = (struct host_cmd_ds_mac_reg_access *) - &resp->params.mac_reg; - reg_rw->offset = cpu_to_le32( - (u32) le16_to_cpu(reg->offset)); - reg_rw->value = reg->value; - break; - } - case HostCmd_CMD_BBP_REG_ACCESS: - { - struct host_cmd_ds_bbp_reg_access *reg; - reg = (struct host_cmd_ds_bbp_reg_access *) - &resp->params.bbp_reg; - reg_rw->offset = cpu_to_le32( - (u32) le16_to_cpu(reg->offset)); - reg_rw->value = cpu_to_le32((u32) reg->value); - break; - } - - case HostCmd_CMD_RF_REG_ACCESS: - { - struct host_cmd_ds_rf_reg_access *reg; - reg = (struct host_cmd_ds_rf_reg_access *) - &resp->params.rf_reg; - reg_rw->offset = cpu_to_le32( - (u32) le16_to_cpu(reg->offset)); - reg_rw->value = cpu_to_le32((u32) reg->value); - break; - } - case HostCmd_CMD_PMIC_REG_ACCESS: - { - struct host_cmd_ds_pmic_reg_access *reg; - reg = (struct host_cmd_ds_pmic_reg_access *) - &resp->params.pmic_reg; - reg_rw->offset = cpu_to_le32( - (u32) le16_to_cpu(reg->offset)); - reg_rw->value = cpu_to_le32((u32) reg->value); - break; - } - case HostCmd_CMD_CAU_REG_ACCESS: - { - struct host_cmd_ds_rf_reg_access *reg; - reg = (struct host_cmd_ds_rf_reg_access *) - &resp->params.rf_reg; - reg_rw->offset = cpu_to_le32( - (u32) le16_to_cpu(reg->offset)); - reg_rw->value = cpu_to_le32((u32) reg->value); - break; - } - case HostCmd_CMD_802_11_EEPROM_ACCESS: - { - struct host_cmd_ds_802_11_eeprom_access - *cmd_eeprom = - (struct host_cmd_ds_802_11_eeprom_access - *) &resp->params.eeprom; - pr_debug("info: EEPROM read len=%x\n", - cmd_eeprom->byte_count); - if (le16_to_cpu(eeprom->byte_count) < - le16_to_cpu( - cmd_eeprom->byte_count)) { - eeprom->byte_count = cpu_to_le16(0); - pr_debug("info: EEPROM read " - "length is too big\n"); - return -1; - } - eeprom->offset = cmd_eeprom->offset; - eeprom->byte_count = cmd_eeprom->byte_count; - if (le16_to_cpu(eeprom->byte_count) > 0) - memcpy(&eeprom->value, - &cmd_eeprom->value, - le16_to_cpu(eeprom->byte_count)); - - break; - } - default: - return -1; - } - } - return 0; -} - -/* - * This function handles the command response of get IBSS coalescing status. - * - * If the received BSSID is different than the current one, the current BSSID, - * beacon interval, ATIM window and ERP information are updated, along with - * changing the ad-hoc state accordingly. - */ -static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = - &(resp->params.ibss_coalescing); - u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - - if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) - return 0; - - dev_dbg(priv->adapter->dev, - "info: new BSSID %pM\n", ibss_coal_resp->bssid); - - /* If rsp has NULL BSSID, Just return..... No Action */ - if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) { - dev_warn(priv->adapter->dev, "new BSSID is NULL\n"); - return 0; - } - - /* If BSSID is diff, modify current BSS parameters */ - if (memcmp(priv->curr_bss_params.bss_descriptor.mac_address, - ibss_coal_resp->bssid, ETH_ALEN)) { - /* BSSID */ - memcpy(priv->curr_bss_params.bss_descriptor.mac_address, - ibss_coal_resp->bssid, ETH_ALEN); - - /* Beacon Interval */ - priv->curr_bss_params.bss_descriptor.beacon_period - = le16_to_cpu(ibss_coal_resp->beacon_interval); - - /* ERP Information */ - priv->curr_bss_params.bss_descriptor.erp_flags = - (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect); - - priv->adhoc_state = ADHOC_COALESCED; - } - - return 0; -} - -/* - * This function handles the command responses. - * - * This is a generic function, which calls command specific - * response handlers based on the command ID. - */ -int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, - u16 cmdresp_no, void *cmd_buf) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_command *resp = - (struct host_cmd_ds_command *) cmd_buf; - void *data_buf = adapter->curr_cmd->data_buf; - - /* If the command is not successful, cleanup and return failure */ - if (resp->result != HostCmd_RESULT_OK) { - mwifiex_process_cmdresp_error(priv, resp); - return -1; - } - /* Command successful, handle response */ - switch (cmdresp_no) { - case HostCmd_CMD_GET_HW_SPEC: - ret = mwifiex_ret_get_hw_spec(priv, resp); - break; - case HostCmd_CMD_MAC_CONTROL: - break; - case HostCmd_CMD_802_11_MAC_ADDRESS: - ret = mwifiex_ret_802_11_mac_address(priv, resp); - break; - case HostCmd_CMD_MAC_MULTICAST_ADR: - ret = mwifiex_ret_mac_multicast_adr(priv, resp); - break; - case HostCmd_CMD_TX_RATE_CFG: - ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_SCAN: - ret = mwifiex_ret_802_11_scan(priv, resp); - adapter->curr_cmd->wait_q_enabled = false; - break; - case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = mwifiex_ret_802_11_scan(priv, resp); - dev_dbg(adapter->dev, - "info: CMD_RESP: BG_SCAN result is ready!\n"); - break; - case HostCmd_CMD_TXPWR_CFG: - ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_PS_MODE_ENH: - ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_HS_CFG_ENH: - ret = mwifiex_ret_802_11_hs_cfg(priv, resp); - break; - case HostCmd_CMD_802_11_ASSOCIATE: - ret = mwifiex_ret_802_11_associate(priv, resp); - break; - case HostCmd_CMD_802_11_DEAUTHENTICATE: - ret = mwifiex_ret_802_11_deauthenticate(priv, resp); - break; - case HostCmd_CMD_802_11_AD_HOC_START: - case HostCmd_CMD_802_11_AD_HOC_JOIN: - ret = mwifiex_ret_802_11_ad_hoc(priv, resp); - break; - case HostCmd_CMD_802_11_AD_HOC_STOP: - ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); - break; - case HostCmd_CMD_802_11_GET_LOG: - ret = mwifiex_ret_get_log(priv, resp, data_buf); - break; - case HostCmd_CMD_RSSI_INFO: - ret = mwifiex_ret_802_11_rssi_info(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_SNMP_MIB: - ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_TX_RATE_QUERY: - ret = mwifiex_ret_802_11_tx_rate_query(priv, resp); - break; - case HostCmd_CMD_802_11_RF_CHANNEL: - ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf); - break; - case HostCmd_CMD_VERSION_EXT: - ret = mwifiex_ret_ver_ext(priv, resp, data_buf); - break; - case HostCmd_CMD_FUNC_INIT: - case HostCmd_CMD_FUNC_SHUTDOWN: - break; - case HostCmd_CMD_802_11_KEY_MATERIAL: - ret = mwifiex_ret_802_11_key_material(priv, resp); - break; - case HostCmd_CMD_802_11D_DOMAIN_INFO: - ret = mwifiex_ret_802_11d_domain_info(priv, resp); - break; - case HostCmd_CMD_11N_ADDBA_REQ: - ret = mwifiex_ret_11n_addba_req(priv, resp); - break; - case HostCmd_CMD_11N_DELBA: - ret = mwifiex_ret_11n_delba(priv, resp); - break; - case HostCmd_CMD_11N_ADDBA_RSP: - ret = mwifiex_ret_11n_addba_resp(priv, resp); - break; - case HostCmd_CMD_RECONFIGURE_TX_BUFF: - adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. - tx_buf.buff_size); - adapter->tx_buf_size = (adapter->tx_buf_size / - MWIFIEX_SDIO_BLOCK_SIZE) * - MWIFIEX_SDIO_BLOCK_SIZE; - adapter->curr_tx_buf_size = adapter->tx_buf_size; - dev_dbg(adapter->dev, - "cmd: max_tx_buf_size=%d, tx_buf_size=%d\n", - adapter->max_tx_buf_size, adapter->tx_buf_size); - - if (adapter->if_ops.update_mp_end_port) - adapter->if_ops.update_mp_end_port(adapter, - le16_to_cpu(resp-> - params. - tx_buf. - mp_end_port)); - break; - case HostCmd_CMD_AMSDU_AGGR_CTRL: - ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf); - break; - case HostCmd_CMD_WMM_GET_STATUS: - ret = mwifiex_ret_wmm_get_status(priv, resp); - break; - case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: - ret = mwifiex_ret_ibss_coalescing_status(priv, resp); - break; - case HostCmd_CMD_MAC_REG_ACCESS: - case HostCmd_CMD_BBP_REG_ACCESS: - case HostCmd_CMD_RF_REG_ACCESS: - case HostCmd_CMD_PMIC_REG_ACCESS: - case HostCmd_CMD_CAU_REG_ACCESS: - case HostCmd_CMD_802_11_EEPROM_ACCESS: - ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf); - break; - case HostCmd_CMD_SET_BSS_MODE: - break; - case HostCmd_CMD_11N_CFG: - ret = mwifiex_ret_11n_cfg(resp, data_buf); - break; - default: - dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", - resp->command); - break; - } - - return ret; -} diff --git a/trunk/drivers/net/wireless/mwifiex/sta_event.c b/trunk/drivers/net/wireless/mwifiex/sta_event.c deleted file mode 100644 index fc265cab0907..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sta_event.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station event handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * This function resets the connection state. - * - * The function is invoked after receiving a disconnect event from firmware, - * and performs the following actions - - * - Set media status to disconnected - * - Clean up Tx and Rx packets - * - Resets SNR/NF/RSSI value in driver - * - Resets security configurations in driver - * - Enables auto data rate - * - Saves the previous SSID and BSSID so that they can - * be used for re-association, if required - * - Erases current SSID and BSSID information - * - Sends a disconnect event to upper layers/applications. - */ -void -mwifiex_reset_connect_state(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - if (!priv->media_connected) - return; - - dev_dbg(adapter->dev, "info: handles disconnect event\n"); - - priv->media_connected = false; - - priv->scan_block = false; - - /* Free Tx and Rx packets, report disconnect to upper layer */ - mwifiex_clean_txrx(priv); - - /* Reset SNR/NF/RSSI values */ - priv->data_rssi_last = 0; - priv->data_nf_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->bcn_rssi_last = 0; - priv->bcn_nf_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - priv->rxpd_rate = 0; - priv->rxpd_htinfo = 0; - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - priv->wpa_ie_len = 0; - - priv->sec_info.wapi_enabled = false; - priv->wapi_ie_len = 0; - priv->sec_info.wapi_key_on = false; - - priv->sec_info.encryption_mode = 0; - - /* Enable auto data rate */ - priv->is_data_rate_auto = true; - priv->data_rate = 0; - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - priv->adhoc_state = ADHOC_IDLE; - priv->adhoc_is_link_sensed = false; - } - - /* - * Memorize the previous SSID and BSSID so - * it could be used for re-assoc - */ - - dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n", - priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); - - dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n", - priv->curr_bss_params.bss_descriptor.ssid.ssid, - priv->curr_bss_params.bss_descriptor.ssid.ssid_len); - - memcpy(&priv->prev_ssid, - &priv->curr_bss_params.bss_descriptor.ssid, - sizeof(struct mwifiex_802_11_ssid)); - - memcpy(priv->prev_bssid, - priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); - - /* Need to erase the current SSID and BSSID info */ - memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); - - adapter->tx_lock_flag = false; - adapter->pps_uapsd_mode = false; - - if (adapter->num_cmd_timeout && adapter->curr_cmd) - return; - priv->media_connected = false; - if (!priv->disconnect) { - priv->disconnect = 1; - dev_dbg(adapter->dev, "info: successfully disconnected from" - " %pM: reason code %d\n", priv->cfg_bssid, - WLAN_REASON_DEAUTH_LEAVING); - cfg80211_disconnected(priv->netdev, - WLAN_REASON_DEAUTH_LEAVING, NULL, 0, - GFP_KERNEL); - queue_work(priv->workqueue, &priv->cfg_workqueue); - } - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - /* Reset wireless stats signal info */ - priv->w_stats.qual.level = 0; - priv->w_stats.qual.noise = 0; -} - -/* - * This function handles events generated by firmware. - * - * This is a generic function and handles all events. - * - * Event specific routines are called by this function based - * upon the generated event cause. - * - * For the following events, the function just forwards them to upper - * layers, optionally recording the change - - * - EVENT_LINK_SENSED - * - EVENT_MIC_ERR_UNICAST - * - EVENT_MIC_ERR_MULTICAST - * - EVENT_PORT_RELEASE - * - EVENT_RSSI_LOW - * - EVENT_SNR_LOW - * - EVENT_MAX_FAIL - * - EVENT_RSSI_HIGH - * - EVENT_SNR_HIGH - * - EVENT_DATA_RSSI_LOW - * - EVENT_DATA_SNR_LOW - * - EVENT_DATA_RSSI_HIGH - * - EVENT_DATA_SNR_HIGH - * - EVENT_LINK_QUALITY - * - EVENT_PRE_BEACON_LOST - * - EVENT_IBSS_COALESCED - * - EVENT_WEP_ICV_ERR - * - EVENT_BW_CHANGE - * - EVENT_HOSTWAKE_STAIE - * - * For the following events, no action is taken - - * - EVENT_MIB_CHANGED - * - EVENT_INIT_DONE - * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL - * - * Rest of the supported events requires driver handling - - * - EVENT_DEAUTHENTICATED - * - EVENT_DISASSOCIATED - * - EVENT_LINK_LOST - * - EVENT_PS_SLEEP - * - EVENT_PS_AWAKE - * - EVENT_DEEP_SLEEP_AWAKE - * - EVENT_HS_ACT_REQ - * - EVENT_ADHOC_BCN_LOST - * - EVENT_BG_SCAN_REPORT - * - EVENT_WMM_STATUS_CHANGE - * - EVENT_ADDBA - * - EVENT_DELBA - * - EVENT_BA_STREAM_TIEMOUT - * - EVENT_AMSDU_AGGR_CTRL - */ -int mwifiex_process_sta_event(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - u32 eventcause = adapter->event_cause; - - switch (eventcause) { - case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: - dev_err(adapter->dev, "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL," - " ignoring it\n"); - break; - case EVENT_LINK_SENSED: - dev_dbg(adapter->dev, "event: LINK_SENSED\n"); - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - if (netif_queue_stopped(priv->netdev)) - netif_wake_queue(priv->netdev); - break; - - case EVENT_DEAUTHENTICATED: - dev_dbg(adapter->dev, "event: Deauthenticated\n"); - adapter->dbg.num_event_deauth++; - if (priv->media_connected) - mwifiex_reset_connect_state(priv); - break; - - case EVENT_DISASSOCIATED: - dev_dbg(adapter->dev, "event: Disassociated\n"); - adapter->dbg.num_event_disassoc++; - if (priv->media_connected) - mwifiex_reset_connect_state(priv); - break; - - case EVENT_LINK_LOST: - dev_dbg(adapter->dev, "event: Link lost\n"); - adapter->dbg.num_event_link_lost++; - if (priv->media_connected) - mwifiex_reset_connect_state(priv); - break; - - case EVENT_PS_SLEEP: - dev_dbg(adapter->dev, "info: EVENT: SLEEP\n"); - - adapter->ps_state = PS_STATE_PRE_SLEEP; - - mwifiex_check_ps_cond(adapter); - break; - - case EVENT_PS_AWAKE: - dev_dbg(adapter->dev, "info: EVENT: AWAKE\n"); - if (!adapter->pps_uapsd_mode && - priv->media_connected && - adapter->sleep_period.period) { - adapter->pps_uapsd_mode = true; - dev_dbg(adapter->dev, - "event: PPS/UAPSD mode activated\n"); - } - adapter->tx_lock_flag = false; - if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { - if (mwifiex_check_last_packet_indication(priv)) { - if (!adapter->data_sent) { - if (!mwifiex_send_null_packet(priv, - MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET - | - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) - adapter->ps_state = - PS_STATE_SLEEP; - return 0; - } - } - } - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_card_req = false; - adapter->pm_wakeup_fw_try = false; - - break; - - case EVENT_DEEP_SLEEP_AWAKE: - adapter->if_ops.wakeup_complete(adapter); - dev_dbg(adapter->dev, "event: DS_AWAKE\n"); - if (adapter->is_deep_sleep) - adapter->is_deep_sleep = false; - break; - - case EVENT_HS_ACT_REQ: - dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_HS_CFG_ENH, - 0, 0, NULL); - break; - - case EVENT_MIC_ERR_UNICAST: - dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n"); - break; - - case EVENT_MIC_ERR_MULTICAST: - dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n"); - break; - case EVENT_MIB_CHANGED: - case EVENT_INIT_DONE: - break; - - case EVENT_ADHOC_BCN_LOST: - dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n"); - priv->adhoc_is_link_sensed = false; - mwifiex_clean_txrx(priv); - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - break; - - case EVENT_BG_SCAN_REPORT: - dev_dbg(adapter->dev, "event: BGS_REPORT\n"); - /* Clear the previous scan result */ - memset(adapter->scan_table, 0x00, - sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); - adapter->num_in_scan_table = 0; - adapter->bcn_buf_end = adapter->bcn_buf; - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_BG_SCAN_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL); - break; - - case EVENT_PORT_RELEASE: - dev_dbg(adapter->dev, "event: PORT RELEASE\n"); - break; - - case EVENT_WMM_STATUS_CHANGE: - dev_dbg(adapter->dev, "event: WMM status changed\n"); - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS, - 0, 0, NULL); - break; - - case EVENT_RSSI_LOW: - dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); - break; - case EVENT_SNR_LOW: - dev_dbg(adapter->dev, "event: Beacon SNR_LOW\n"); - break; - case EVENT_MAX_FAIL: - dev_dbg(adapter->dev, "event: MAX_FAIL\n"); - break; - case EVENT_RSSI_HIGH: - dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); - break; - case EVENT_SNR_HIGH: - dev_dbg(adapter->dev, "event: Beacon SNR_HIGH\n"); - break; - case EVENT_DATA_RSSI_LOW: - dev_dbg(adapter->dev, "event: Data RSSI_LOW\n"); - break; - case EVENT_DATA_SNR_LOW: - dev_dbg(adapter->dev, "event: Data SNR_LOW\n"); - break; - case EVENT_DATA_RSSI_HIGH: - dev_dbg(adapter->dev, "event: Data RSSI_HIGH\n"); - break; - case EVENT_DATA_SNR_HIGH: - dev_dbg(adapter->dev, "event: Data SNR_HIGH\n"); - break; - case EVENT_LINK_QUALITY: - dev_dbg(adapter->dev, "event: Link Quality\n"); - break; - case EVENT_PRE_BEACON_LOST: - dev_dbg(adapter->dev, "event: Pre-Beacon Lost\n"); - break; - case EVENT_IBSS_COALESCED: - dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, - HostCmd_ACT_GEN_GET, 0, NULL); - break; - case EVENT_ADDBA: - dev_dbg(adapter->dev, "event: ADDBA Request\n"); - mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP, - HostCmd_ACT_GEN_SET, 0, - adapter->event_body); - break; - case EVENT_DELBA: - dev_dbg(adapter->dev, "event: DELBA Request\n"); - mwifiex_11n_delete_ba_stream(priv, adapter->event_body); - break; - case EVENT_BA_STREAM_TIEMOUT: - dev_dbg(adapter->dev, "event: BA Stream timeout\n"); - mwifiex_11n_ba_stream_timeout(priv, - (struct host_cmd_ds_11n_batimeout - *) - adapter->event_body); - break; - case EVENT_AMSDU_AGGR_CTRL: - dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", - *(u16 *) adapter->event_body); - adapter->tx_buf_size = - min(adapter->curr_tx_buf_size, - le16_to_cpu(*(__le16 *) adapter->event_body)); - dev_dbg(adapter->dev, "event: tx_buf_size %d\n", - adapter->tx_buf_size); - break; - - case EVENT_WEP_ICV_ERR: - dev_dbg(adapter->dev, "event: WEP ICV error\n"); - break; - - case EVENT_BW_CHANGE: - dev_dbg(adapter->dev, "event: BW Change\n"); - break; - - case EVENT_HOSTWAKE_STAIE: - dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); - break; - default: - dev_dbg(adapter->dev, "event: unknown event id: %#x\n", - eventcause); - break; - } - - return ret; -} diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c deleted file mode 100644 index e7adaab35226..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ /dev/null @@ -1,1605 +0,0 @@ -/* - * Marvell Wireless LAN device driver: functions for station ioctl - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "cfg80211.h" - -/* - * Copies the multicast address list from device to driver. - * - * This function does not validate the destination memory for - * size, and the calling function must ensure enough memory is - * available. - */ -int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, - struct net_device *dev) -{ - int i = 0; - struct netdev_hw_addr *ha; - - netdev_for_each_mc_addr(ha, dev) - memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN); - - return i; -} - -/* - * Wait queue completion handler. - * - * This function waits on a cmd wait queue. It also cancels the pending - * request after waking up, in case of errors. - */ -int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) -{ - bool cancel_flag = false; - int status = adapter->cmd_wait_q.status; - - dev_dbg(adapter->dev, "cmd pending\n"); - atomic_inc(&adapter->cmd_pending); - - /* Status pending, wake up main process */ - queue_work(adapter->workqueue, &adapter->main_work); - - /* Wait for completion */ - wait_event_interruptible(adapter->cmd_wait_q.wait, - adapter->cmd_wait_q.condition); - if (!adapter->cmd_wait_q.condition) - cancel_flag = true; - - if (cancel_flag) { - mwifiex_cancel_pending_ioctl(adapter); - dev_dbg(adapter->dev, "cmd cancel\n"); - } - adapter->cmd_wait_q.status = 0; - - return status; -} - -/* - * This function prepares the correct firmware command and - * issues it to set the multicast list. - * - * This function can be used to enable promiscuous mode, or enable all - * multicast packets, or to enable selective multicast. - */ -int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, - struct mwifiex_multicast_list *mcast_list) -{ - int ret = 0; - u16 old_pkt_filter; - - old_pkt_filter = priv->curr_pkt_filter; - - if (mcast_list->mode == MWIFIEX_PROMISC_MODE) { - dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n"); - priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; - priv->curr_pkt_filter &= - ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - } else { - /* Multicast */ - priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; - if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) { - dev_dbg(priv->adapter->dev, - "info: Enabling All Multicast!\n"); - priv->curr_pkt_filter |= - HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - } else { - priv->curr_pkt_filter &= - ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - if (mcast_list->num_multicast_addr) { - dev_dbg(priv->adapter->dev, - "info: Set multicast list=%d\n", - mcast_list->num_multicast_addr); - /* Set multicast addresses to firmware */ - if (old_pkt_filter == priv->curr_pkt_filter) { - /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, 0, - mcast_list); - } else { - /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, 0, - mcast_list); - } - } - } - } - dev_dbg(priv->adapter->dev, - "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", - old_pkt_filter, priv->curr_pkt_filter); - if (old_pkt_filter != priv->curr_pkt_filter) { - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, - 0, &priv->curr_pkt_filter); - } - - return ret; -} - -/* - * In Ad-Hoc mode, the IBSS is created if not found in scan list. - * In both Ad-Hoc and infra mode, an deauthentication is performed - * first. - */ -int mwifiex_bss_start(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *ssid_bssid) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - s32 i = -1; - - priv->scan_block = false; - if (!ssid_bssid) - return -1; - - if (priv->bss_mode == NL80211_IFTYPE_STATION) { - /* Infra mode */ - ret = mwifiex_deauthenticate(priv, NULL); - if (ret) - return ret; - - /* Search for the requested SSID in the scan table */ - if (ssid_bssid->ssid.ssid_len) - i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, - NULL, NL80211_IFTYPE_STATION); - else - i = mwifiex_find_bssid_in_list(priv, - (u8 *) &ssid_bssid->bssid, - NL80211_IFTYPE_STATION); - if (i < 0) - return -1; - - dev_dbg(adapter->dev, - "info: SSID found in scan list ... associating...\n"); - - /* Clear any past association response stored for - * application retrieval */ - priv->assoc_rsp_size = 0; - ret = mwifiex_associate(priv, &adapter->scan_table[i]); - if (ret) - return ret; - } else { - /* Adhoc mode */ - /* If the requested SSID matches current SSID, return */ - if (ssid_bssid->ssid.ssid_len && - (!mwifiex_ssid_cmp - (&priv->curr_bss_params.bss_descriptor.ssid, - &ssid_bssid->ssid))) - return 0; - - /* Exit Adhoc mode first */ - dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); - ret = mwifiex_deauthenticate(priv, NULL); - if (ret) - return ret; - - priv->adhoc_is_link_sensed = false; - - /* Search for the requested network in the scan table */ - if (ssid_bssid->ssid.ssid_len) - i = mwifiex_find_ssid_in_list(priv, - &ssid_bssid->ssid, NULL, - NL80211_IFTYPE_ADHOC); - else - i = mwifiex_find_bssid_in_list(priv, - (u8 *)&ssid_bssid->bssid, - NL80211_IFTYPE_ADHOC); - - if (i >= 0) { - dev_dbg(adapter->dev, "info: network found in scan" - " list. Joining...\n"); - ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]); - if (ret) - return ret; - } else { - dev_dbg(adapter->dev, "info: Network not found in " - "the list, creating adhoc with ssid = %s\n", - ssid_bssid->ssid.ssid); - ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid); - if (ret) - return ret; - } - } - - return ret; -} - -/* - * IOCTL request handler to set host sleep configuration. - * - * This function prepares the correct firmware command and - * issues it. - */ -int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, - int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg) - -{ - struct mwifiex_adapter *adapter = priv->adapter; - int status = 0; - u32 prev_cond = 0; - - if (!hs_cfg) - return -ENOMEM; - - switch (action) { - case HostCmd_ACT_GEN_SET: - if (adapter->pps_uapsd_mode) { - dev_dbg(adapter->dev, "info: Host Sleep IOCTL" - " is blocked in UAPSD/PPS mode\n"); - status = -1; - break; - } - if (hs_cfg->is_invoke_hostcmd) { - if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { - if (!adapter->is_hs_configured) - /* Already cancelled */ - break; - /* Save previous condition */ - prev_cond = le32_to_cpu(adapter->hs_cfg - .conditions); - adapter->hs_cfg.conditions = - cpu_to_le32(hs_cfg->conditions); - } else if (hs_cfg->conditions) { - adapter->hs_cfg.conditions = - cpu_to_le32(hs_cfg->conditions); - adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; - if (hs_cfg->gap) - adapter->hs_cfg.gap = (u8)hs_cfg->gap; - } else if (adapter->hs_cfg.conditions == - cpu_to_le32( - HOST_SLEEP_CFG_CANCEL)) { - /* Return failure if no parameters for HS - enable */ - status = -1; - break; - } - if (cmd_type == MWIFIEX_SYNC_CMD) - status = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_HS_CFG_ENH, - HostCmd_ACT_GEN_SET, 0, - &adapter->hs_cfg); - else - status = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_HS_CFG_ENH, - HostCmd_ACT_GEN_SET, 0, - &adapter->hs_cfg); - if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) - /* Restore previous condition */ - adapter->hs_cfg.conditions = - cpu_to_le32(prev_cond); - } else { - adapter->hs_cfg.conditions = - cpu_to_le32(hs_cfg->conditions); - adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; - adapter->hs_cfg.gap = (u8)hs_cfg->gap; - } - break; - case HostCmd_ACT_GEN_GET: - hs_cfg->conditions = le32_to_cpu(adapter->hs_cfg.conditions); - hs_cfg->gpio = adapter->hs_cfg.gpio; - hs_cfg->gap = adapter->hs_cfg.gap; - break; - default: - status = -1; - break; - } - - return status; -} - -/* - * Sends IOCTL request to cancel the existing Host Sleep configuration. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) -{ - struct mwifiex_ds_hs_cfg hscfg; - - hscfg.conditions = HOST_SLEEP_CFG_CANCEL; - hscfg.is_invoke_hostcmd = true; - - return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - cmd_type, &hscfg); -} -EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); - -/* - * Sends IOCTL request to cancel the existing Host Sleep configuration. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_enable_hs(struct mwifiex_adapter *adapter) -{ - struct mwifiex_ds_hs_cfg hscfg; - - if (adapter->hs_activated) { - dev_dbg(adapter->dev, "cmd: HS Already actived\n"); - return true; - } - - adapter->hs_activate_wait_q_woken = false; - - memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param)); - hscfg.is_invoke_hostcmd = true; - - if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_STA), - HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, - &hscfg)) { - dev_err(adapter->dev, "IOCTL request HS enable failed\n"); - return false; - } - - wait_event_interruptible(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken); - - return true; -} -EXPORT_SYMBOL_GPL(mwifiex_enable_hs); - -/* - * IOCTL request handler to get BSS information. - * - * This function collates the information from different driver structures - * to send to the user. - */ -int mwifiex_get_bss_info(struct mwifiex_private *priv, - struct mwifiex_bss_info *info) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *bss_desc; - s32 tbl_idx = 0; - - if (!info) - return -1; - - bss_desc = &priv->curr_bss_params.bss_descriptor; - - info->bss_mode = priv->bss_mode; - - memcpy(&info->ssid, &bss_desc->ssid, - sizeof(struct mwifiex_802_11_ssid)); - - memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); - - info->bss_chan = bss_desc->channel; - - info->region_code = adapter->region_code; - - /* Scan table index if connected */ - info->scan_table_idx = 0; - if (priv->media_connected) { - tbl_idx = - mwifiex_find_ssid_in_list(priv, &bss_desc->ssid, - bss_desc->mac_address, - priv->bss_mode); - if (tbl_idx >= 0) - info->scan_table_idx = tbl_idx; - } - - info->media_connected = priv->media_connected; - - info->max_power_level = priv->max_tx_power_level; - info->min_power_level = priv->min_tx_power_level; - - info->adhoc_state = priv->adhoc_state; - - info->bcn_nf_last = priv->bcn_nf_last; - - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) - info->wep_status = true; - else - info->wep_status = false; - - info->is_hs_configured = adapter->is_hs_configured; - info->is_deep_sleep = adapter->is_deep_sleep; - - return 0; -} - -/* - * The function sets band configurations. - * - * it performs extra checks to make sure the Ad-Hoc - * band and channel are compatible. Otherwise it returns an error. - * - */ -int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, - struct mwifiex_ds_band_cfg *radio_cfg) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 infra_band = 0; - u8 adhoc_band = 0; - u32 adhoc_channel = 0; - - infra_band = (u8) radio_cfg->config_bands; - adhoc_band = (u8) radio_cfg->adhoc_start_band; - adhoc_channel = radio_cfg->adhoc_channel; - - /* SET Infra band */ - if ((infra_band | adapter->fw_bands) & ~adapter->fw_bands) - return -1; - - adapter->config_bands = infra_band; - - /* SET Ad-hoc Band */ - if ((adhoc_band | adapter->fw_bands) & ~adapter->fw_bands) - return -1; - - if (adhoc_band) - adapter->adhoc_start_band = adhoc_band; - adapter->chan_offset = (u8) radio_cfg->sec_chan_offset; - /* - * If no adhoc_channel is supplied verify if the existing adhoc - * channel compiles with new adhoc_band - */ - if (!adhoc_channel) { - if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, adapter->adhoc_start_band, - priv->adhoc_channel)) { - /* Pass back the default channel */ - radio_cfg->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - if ((adapter->adhoc_start_band & BAND_A) - || (adapter->adhoc_start_band & BAND_AN)) - radio_cfg->adhoc_channel = - DEFAULT_AD_HOC_CHANNEL_A; - } - } else { /* Retrurn error if adhoc_band and - adhoc_channel combination is invalid */ - if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, adapter->adhoc_start_band, (u16) adhoc_channel)) - return -1; - priv->adhoc_channel = (u8) adhoc_channel; - } - if ((adhoc_band & BAND_GN) || (adhoc_band & BAND_AN)) - adapter->adhoc_11n_enabled = true; - else - adapter->adhoc_11n_enabled = false; - - return 0; -} - -/* - * IOCTL request handler to set/get active channel. - * - * This function performs validity checking on channel/frequency - * compatibility and returns failure if not valid. - */ -int mwifiex_bss_set_channel(struct mwifiex_private *priv, - struct mwifiex_chan_freq_power *chan) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_chan_freq_power *cfp = NULL; - - if (!chan) - return -1; - - if (!chan->channel && !chan->freq) - return -1; - if (adapter->adhoc_start_band & BAND_AN) - adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; - else if (adapter->adhoc_start_band & BAND_A) - adapter->adhoc_start_band = BAND_G | BAND_B; - if (chan->channel) { - if (chan->channel <= MAX_CHANNEL_BAND_BG) - cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, 0, (u16) chan->channel); - if (!cfp) { - cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211 - (priv, BAND_A, (u16) chan->channel); - if (cfp) { - if (adapter->adhoc_11n_enabled) - adapter->adhoc_start_band = BAND_A - | BAND_AN; - else - adapter->adhoc_start_band = BAND_A; - } - } - } else { - if (chan->freq <= MAX_FREQUENCY_BAND_BG) - cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211( - priv, 0, chan->freq); - if (!cfp) { - cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211 - (priv, BAND_A, chan->freq); - if (cfp) { - if (adapter->adhoc_11n_enabled) - adapter->adhoc_start_band = BAND_A - | BAND_AN; - else - adapter->adhoc_start_band = BAND_A; - } - } - } - if (!cfp || !cfp->channel) { - dev_err(adapter->dev, "invalid channel/freq\n"); - return -1; - } - priv->adhoc_channel = (u8) cfp->channel; - chan->channel = cfp->channel; - chan->freq = cfp->freq; - - return 0; -} - -/* - * IOCTL request handler to set/get Ad-Hoc channel. - * - * This function prepares the correct firmware command and - * issues it to set or get the ad-hoc channel. - */ -static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, - u16 action, u16 *channel) -{ - if (action == HostCmd_ACT_GEN_GET) { - if (!priv->media_connected) { - *channel = priv->adhoc_channel; - return 0; - } - } else { - priv->adhoc_channel = (u8) *channel; - } - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL, - action, 0, channel); -} - -/* - * IOCTL request handler to find a particular BSS. - * - * The BSS can be searched with either a BSSID or a SSID. If none of - * these are provided, just the best BSS (best RSSI) is returned. - */ -int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, - struct mwifiex_ssid_bssid *ssid_bssid) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *bss_desc; - u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - u8 mac[ETH_ALEN]; - int i = 0; - - if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) { - i = mwifiex_find_bssid_in_list(priv, - (u8 *) ssid_bssid->bssid, - priv->bss_mode); - if (i < 0) { - memcpy(mac, ssid_bssid->bssid, sizeof(mac)); - dev_err(adapter->dev, "cannot find bssid %pM\n", mac); - return -1; - } - bss_desc = &adapter->scan_table[i]; - memcpy(&ssid_bssid->ssid, &bss_desc->ssid, - sizeof(struct mwifiex_802_11_ssid)); - } else if (ssid_bssid->ssid.ssid_len) { - i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL, - priv->bss_mode); - if (i < 0) { - dev_err(adapter->dev, "cannot find ssid %s\n", - ssid_bssid->ssid.ssid); - return -1; - } - bss_desc = &adapter->scan_table[i]; - memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN); - } else { - return mwifiex_find_best_network(priv, ssid_bssid); - } - - return 0; -} - -/* - * IOCTL request handler to change Ad-Hoc channel. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - * - * The function follows the following steps to perform the change - - * - Get current IBSS information - * - Get current channel - * - If no change is required, return - * - If not connected, change channel and return - * - If connected, - * - Disconnect - * - Change channel - * - Perform specific SSID scan with same SSID - * - Start/Join the IBSS - */ -int -mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) -{ - int ret = 0; - struct mwifiex_bss_info bss_info; - struct mwifiex_ssid_bssid ssid_bssid; - u16 curr_chan = 0; - - memset(&bss_info, 0, sizeof(bss_info)); - - /* Get BSS information */ - if (mwifiex_get_bss_info(priv, &bss_info)) - return -1; - - /* Get current channel */ - ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, - &curr_chan); - - if (curr_chan == channel) { - ret = 0; - goto done; - } - dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n", - curr_chan, channel); - - if (!bss_info.media_connected) { - ret = 0; - goto done; - } - - /* Do disonnect */ - memset(&ssid_bssid, 0, ETH_ALEN); - ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); - - ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, - (u16 *) &channel); - - /* Do specific SSID scanning */ - if (mwifiex_request_scan(priv, &bss_info.ssid)) { - ret = -1; - goto done; - } - /* Start/Join Adhoc network */ - memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); - memcpy(&ssid_bssid.ssid, &bss_info.ssid, - sizeof(struct mwifiex_802_11_ssid)); - - ret = mwifiex_bss_start(priv, &ssid_bssid); -done: - return ret; -} - -/* - * IOCTL request handler to get rate. - * - * This function prepares the correct firmware command and - * issues it to get the current rate if it is connected, - * otherwise, the function returns the lowest supported rate - * for the band. - */ -static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, - struct mwifiex_rate_cfg *rate_cfg) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - rate_cfg->is_rate_auto = priv->is_data_rate_auto; - if (!priv->media_connected) { - switch (adapter->config_bands) { - case BAND_B: - /* Return the lowest supported rate for B band */ - rate_cfg->rate = supported_rates_b[0] & 0x7f; - break; - case BAND_G: - case BAND_G | BAND_GN: - /* Return the lowest supported rate for G band */ - rate_cfg->rate = supported_rates_g[0] & 0x7f; - break; - case BAND_B | BAND_G: - case BAND_A | BAND_B | BAND_G: - case BAND_A | BAND_B: - case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN: - case BAND_B | BAND_G | BAND_GN: - /* Return the lowest supported rate for BG band */ - rate_cfg->rate = supported_rates_bg[0] & 0x7f; - break; - case BAND_A: - case BAND_A | BAND_G: - case BAND_A | BAND_G | BAND_AN | BAND_GN: - case BAND_A | BAND_AN: - /* Return the lowest supported rate for A band */ - rate_cfg->rate = supported_rates_a[0] & 0x7f; - break; - case BAND_GN: - /* Return the lowest supported rate for N band */ - rate_cfg->rate = supported_rates_n[0] & 0x7f; - break; - default: - dev_warn(adapter->dev, "invalid band %#x\n", - adapter->config_bands); - break; - } - } else { - return mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL); - } - - return 0; -} - -/* - * IOCTL request handler to set rate. - * - * This function prepares the correct firmware command and - * issues it to set the current rate. - * - * The function also performs validation checking on the supplied value. - */ -static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, - struct mwifiex_rate_cfg *rate_cfg) -{ - u8 rates[MWIFIEX_SUPPORTED_RATES]; - u8 *rate = NULL; - int rate_index = 0; - u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; - u32 i = 0; - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - - if (rate_cfg->is_rate_auto) { - memset(bitmap_rates, 0, sizeof(bitmap_rates)); - /* Support all HR/DSSS rates */ - bitmap_rates[0] = 0x000F; - /* Support all OFDM rates */ - bitmap_rates[1] = 0x00FF; - /* Support all HT-MCSs rate */ - for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates) - 3; i++) - bitmap_rates[i + 2] = 0xFFFF; - bitmap_rates[9] = 0x3FFF; - } else { - memset(rates, 0, sizeof(rates)); - mwifiex_get_active_data_rates(priv, rates); - rate = rates; - for (i = 0; (rate[i] && i < MWIFIEX_SUPPORTED_RATES); i++) { - dev_dbg(adapter->dev, "info: rate=%#x wanted=%#x\n", - rate[i], rate_cfg->rate); - if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f)) - break; - } - if (!rate[i] || (i == MWIFIEX_SUPPORTED_RATES)) { - dev_err(adapter->dev, "fixed data rate %#x is out " - "of range\n", rate_cfg->rate); - return -1; - } - memset(bitmap_rates, 0, sizeof(bitmap_rates)); - - rate_index = mwifiex_data_rate_to_index(rate_cfg->rate); - - /* Only allow b/g rates to be set */ - if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 && - rate_index <= MWIFIEX_RATE_INDEX_HRDSSS3) { - bitmap_rates[0] = 1 << rate_index; - } else { - rate_index -= 1; /* There is a 0x00 in the table */ - if (rate_index >= MWIFIEX_RATE_INDEX_OFDM0 && - rate_index <= MWIFIEX_RATE_INDEX_OFDM7) - bitmap_rates[1] = 1 << (rate_index - - MWIFIEX_RATE_INDEX_OFDM0); - } - } - - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_SET, 0, bitmap_rates); - - return ret; -} - -/* - * IOCTL request handler to set/get rate. - * - * This function can be used to set/get either the rate value or the - * rate index. - */ -static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, - struct mwifiex_rate_cfg *rate_cfg) -{ - int status = 0; - - if (!rate_cfg) - return -1; - - if (rate_cfg->action == HostCmd_ACT_GEN_GET) - status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg); - else - status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg); - - return status; -} - -/* - * Sends IOCTL request to get the data rate. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, - struct mwifiex_rate_cfg *rate) -{ - int ret = 0; - - memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); - rate->action = HostCmd_ACT_GEN_GET; - ret = mwifiex_rate_ioctl_cfg(priv, rate); - - if (!ret) { - if (rate && rate->is_rate_auto) - rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, - priv->tx_htinfo); - else if (rate) - rate->rate = priv->data_rate; - } else { - ret = -1; - } - - return ret; -} - -/* - * IOCTL request handler to set tx power configuration. - * - * This function prepares the correct firmware command and - * issues it. - * - * For non-auto power mode, all the following power groups are set - - * - Modulation class HR/DSSS - * - Modulation class OFDM - * - Modulation class HTBW20 - * - Modulation class HTBW40 - */ -int mwifiex_set_tx_power(struct mwifiex_private *priv, - struct mwifiex_power_cfg *power_cfg) -{ - int ret = 0; - struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL; - struct mwifiex_types_power_group *pg_tlv = NULL; - struct mwifiex_power_group *pg = NULL; - u8 *buf = NULL; - u16 dbm = 0; - - if (!power_cfg->is_power_auto) { - dbm = (u16) power_cfg->power_level; - if ((dbm < priv->min_tx_power_level) || - (dbm > priv->max_tx_power_level)) { - dev_err(priv->adapter->dev, "txpower value %d dBm" - " is out of range (%d dBm-%d dBm)\n", - dbm, priv->min_tx_power_level, - priv->max_tx_power_level); - return -1; - } - } - buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL); - if (!buf) { - dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", - __func__); - return -1; - } - - txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; - txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); - if (!power_cfg->is_power_auto) { - txp_cfg->mode = cpu_to_le32(1); - pg_tlv = (struct mwifiex_types_power_group *) (buf + - sizeof(struct host_cmd_ds_txpwr_cfg)); - pg_tlv->type = TLV_TYPE_POWER_GROUP; - pg_tlv->length = 4 * sizeof(struct mwifiex_power_group); - pg = (struct mwifiex_power_group *) (buf + - sizeof(struct host_cmd_ds_txpwr_cfg) + - sizeof(struct mwifiex_types_power_group)); - /* Power group for modulation class HR/DSSS */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x03; - pg->modulation_class = MOD_CLASS_HR_DSSS; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg++; - /* Power group for modulation class OFDM */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x07; - pg->modulation_class = MOD_CLASS_OFDM; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg++; - /* Power group for modulation class HTBW20 */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x20; - pg->modulation_class = MOD_CLASS_HT; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg->ht_bandwidth = HT_BW_20; - pg++; - /* Power group for modulation class HTBW40 */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x20; - pg->modulation_class = MOD_CLASS_HT; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg->ht_bandwidth = HT_BW_40; - } - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, - HostCmd_ACT_GEN_SET, 0, buf); - - kfree(buf); - return ret; -} - -/* - * IOCTL request handler to get power save mode. - * - * This function prepares the correct firmware command and - * issues it. - */ -int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - u16 sub_cmd; - - if (*ps_mode) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - else - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - sub_cmd, BITMAP_STA_PS, NULL); - if ((!ret) && (sub_cmd == DIS_AUTO_PS)) - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, - 0, NULL); - - return ret; -} - -/* - * IOCTL request handler to set/reset WPA IE. - * - * The supplied WPA IE is treated as a opaque buffer. Only the first field - * is checked to determine WPA version. If buffer length is zero, the existing - * WPA IE is reset. - */ -static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv, - u8 *ie_data_ptr, u16 ie_len) -{ - if (ie_len) { - if (ie_len > sizeof(priv->wpa_ie)) { - dev_err(priv->adapter->dev, - "failed to copy WPA IE, too big\n"); - return -1; - } - memcpy(priv->wpa_ie, ie_data_ptr, ie_len); - priv->wpa_ie_len = (u8) ie_len; - dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n", - priv->wpa_ie_len, priv->wpa_ie[0]); - - if (priv->wpa_ie[0] == WLAN_EID_WPA) { - priv->sec_info.wpa_enabled = true; - } else if (priv->wpa_ie[0] == WLAN_EID_RSN) { - priv->sec_info.wpa2_enabled = true; - } else { - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - } - } else { - memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie)); - priv->wpa_ie_len = 0; - dev_dbg(priv->adapter->dev, "info: reset wpa_ie_len=%d IE=%#x\n", - priv->wpa_ie_len, priv->wpa_ie[0]); - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - } - - return 0; -} - -/* - * IOCTL request handler to set/reset WAPI IE. - * - * The supplied WAPI IE is treated as a opaque buffer. Only the first field - * is checked to internally enable WAPI. If buffer length is zero, the existing - * WAPI IE is reset. - */ -static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, - u8 *ie_data_ptr, u16 ie_len) -{ - if (ie_len) { - if (ie_len > sizeof(priv->wapi_ie)) { - dev_dbg(priv->adapter->dev, - "info: failed to copy WAPI IE, too big\n"); - return -1; - } - memcpy(priv->wapi_ie, ie_data_ptr, ie_len); - priv->wapi_ie_len = ie_len; - dev_dbg(priv->adapter->dev, "cmd: Set wapi_ie_len=%d IE=%#x\n", - priv->wapi_ie_len, priv->wapi_ie[0]); - - if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY) - priv->sec_info.wapi_enabled = true; - } else { - memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie)); - priv->wapi_ie_len = ie_len; - dev_dbg(priv->adapter->dev, - "info: Reset wapi_ie_len=%d IE=%#x\n", - priv->wapi_ie_len, priv->wapi_ie[0]); - priv->sec_info.wapi_enabled = false; - } - return 0; -} - -/* - * IOCTL request handler to set WAPI key. - * - * This function prepares the correct firmware command and - * issues it. - */ -static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - encrypt_key); -} - -/* - * IOCTL request handler to set WEP network key. - * - * This function prepares the correct firmware command and - * issues it, after validation checks. - */ -static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - int ret = 0; - struct mwifiex_wep_key *wep_key = NULL; - int index; - - if (priv->wep_key_curr_index >= NUM_WEP_KEYS) - priv->wep_key_curr_index = 0; - wep_key = &priv->wep_key[priv->wep_key_curr_index]; - index = encrypt_key->key_index; - if (encrypt_key->key_disable) { - priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; - } else if (!encrypt_key->key_len) { - /* Copy the required key as the current key */ - wep_key = &priv->wep_key[index]; - if (!wep_key->key_length) { - dev_err(priv->adapter->dev, - "key not set, so cannot enable it\n"); - return -1; - } - priv->wep_key_curr_index = (u16) index; - priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; - } else { - wep_key = &priv->wep_key[index]; - memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); - /* Copy the key in the driver */ - memcpy(wep_key->key_material, - encrypt_key->key_material, - encrypt_key->key_len); - wep_key->key_index = index; - wep_key->key_length = encrypt_key->key_len; - priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; - } - if (wep_key->key_length) { - /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, 0, NULL); - if (ret) - return ret; - } - if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) - priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; - else - priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; - - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter); - - return ret; -} - -/* - * IOCTL request handler to set WPA key. - * - * This function prepares the correct firmware command and - * issues it, after validation checks. - * - * Current driver only supports key length of up to 32 bytes. - * - * This function can also be used to disable a currently set key. - */ -static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - int ret = 0; - u8 remove_key = false; - struct host_cmd_ds_802_11_key_material *ibss_key; - - /* Current driver only supports key length of up to 32 bytes */ - if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) { - dev_err(priv->adapter->dev, "key length too long\n"); - return -1; - } - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - /* - * IBSS/WPA-None uses only one key (Group) for both receiving - * and sending unicast and multicast packets. - */ - /* Send the key as PTK to firmware */ - encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - encrypt_key); - if (ret) - return ret; - - ibss_key = &priv->aes_key; - memset(ibss_key, 0, - sizeof(struct host_cmd_ds_802_11_key_material)); - /* Copy the key in the driver */ - memcpy(ibss_key->key_param_set.key, encrypt_key->key_material, - encrypt_key->key_len); - memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len, - sizeof(ibss_key->key_param_set.key_len)); - ibss_key->key_param_set.key_type_id - = cpu_to_le16(KEY_TYPE_ID_TKIP); - ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED); - - /* Send the key as GTK to firmware */ - encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST; - } - - if (!encrypt_key->key_index) - encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; - - if (remove_key) - ret = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED), - encrypt_key); - else - ret = mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - encrypt_key); - - return ret; -} - -/* - * IOCTL request handler to set/get network keys. - * - * This is a generic key handling function which supports WEP, WPA - * and WAPI. - */ -static int -mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - int status = 0; - - if (encrypt_key->is_wapi_key) - status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); - else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104) - status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key); - else - status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key); - return status; -} - -/* - * This function returns the driver version. - */ -int -mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, - int max_len) -{ - union { - u32 l; - u8 c[4]; - } ver; - char fw_ver[32]; - - ver.l = adapter->fw_release_number; - sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); - - snprintf(version, max_len, driver_version, fw_ver); - - dev_dbg(adapter->dev, "info: MWIFIEX VERSION: %s\n", version); - - return 0; -} - -/* - * Sends IOCTL request to get signal information. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_get_signal_info(struct mwifiex_private *priv, - struct mwifiex_ds_get_signal *signal) -{ - struct mwifiex_ds_get_signal info; - int status = 0; - - memset(&info, 0, sizeof(struct mwifiex_ds_get_signal)); - info.selector = ALL_RSSI_INFO_MASK; - - /* Signal info can be obtained only if connected */ - if (!priv->media_connected) { - dev_dbg(priv->adapter->dev, - "info: Can not get signal in disconnected state\n"); - return -1; - } - - status = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, - HostCmd_ACT_GEN_GET, 0, signal); - - if (!status) { - if (signal) - memcpy(signal, &info, - sizeof(struct mwifiex_ds_get_signal)); - if (info.selector & BCN_RSSI_AVG_MASK) - priv->w_stats.qual.level = info.bcn_rssi_avg; - if (info.selector & BCN_NF_AVG_MASK) - priv->w_stats.qual.noise = info.bcn_nf_avg; - } - - return status; -} - -/* - * Sends IOCTL request to set encoding parameters. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, - int key_len, u8 key_index, int disable) -{ - struct mwifiex_ds_encrypt_key encrypt_key; - - memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); - encrypt_key.key_len = key_len; - if (!disable) { - encrypt_key.key_index = key_index; - if (key_len) - memcpy(encrypt_key.key_material, key, key_len); - } else { - encrypt_key.key_disable = true; - } - - return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); -} - -/* - * Sends IOCTL request to get extended version. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_get_ver_ext(struct mwifiex_private *priv) -{ - struct mwifiex_ver_ext ver_ext; - - memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); - if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, - HostCmd_ACT_GEN_GET, 0, &ver_ext)) - return -1; - - return 0; -} - -/* - * Sends IOCTL request to get statistics information. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_get_stats_info(struct mwifiex_private *priv, - struct mwifiex_ds_get_stats *log) -{ - int ret = 0; - struct mwifiex_ds_get_stats get_log; - - memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, - HostCmd_ACT_GEN_GET, 0, &get_log); - - if (!ret) { - if (log) - memcpy(log, &get_log, sizeof(struct - mwifiex_ds_get_stats)); - priv->w_stats.discard.fragment = get_log.fcs_error; - priv->w_stats.discard.retries = get_log.retry; - priv->w_stats.discard.misc = get_log.ack_failure; - } - - return ret; -} - -/* - * IOCTL request handler to read/write register. - * - * This function prepares the correct firmware command and - * issues it. - * - * Access to the following registers are supported - - * - MAC - * - BBP - * - RF - * - PMIC - * - CAU - */ -static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, - struct mwifiex_ds_reg_rw *reg_rw, - u16 action) -{ - u16 cmd_no; - - switch (le32_to_cpu(reg_rw->type)) { - case MWIFIEX_REG_MAC: - cmd_no = HostCmd_CMD_MAC_REG_ACCESS; - break; - case MWIFIEX_REG_BBP: - cmd_no = HostCmd_CMD_BBP_REG_ACCESS; - break; - case MWIFIEX_REG_RF: - cmd_no = HostCmd_CMD_RF_REG_ACCESS; - break; - case MWIFIEX_REG_PMIC: - cmd_no = HostCmd_CMD_PMIC_REG_ACCESS; - break; - case MWIFIEX_REG_CAU: - cmd_no = HostCmd_CMD_CAU_REG_ACCESS; - break; - default: - return -1; - } - - return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); - -} - -/* - * Sends IOCTL request to write to a register. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 reg_value) -{ - struct mwifiex_ds_reg_rw reg_rw; - - reg_rw.type = cpu_to_le32(reg_type); - reg_rw.offset = cpu_to_le32(reg_offset); - reg_rw.value = cpu_to_le32(reg_value); - - return mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET); -} - -/* - * Sends IOCTL request to read from a register. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 *value) -{ - int ret = 0; - struct mwifiex_ds_reg_rw reg_rw; - - reg_rw.type = cpu_to_le32(reg_type); - reg_rw.offset = cpu_to_le32(reg_offset); - ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_GET); - - if (ret) - goto done; - - *value = le32_to_cpu(reg_rw.value); - -done: - return ret; -} - -/* - * Sends IOCTL request to read from EEPROM. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, - u8 *value) -{ - int ret = 0; - struct mwifiex_ds_read_eeprom rd_eeprom; - - rd_eeprom.offset = cpu_to_le16((u16) offset); - rd_eeprom.byte_count = cpu_to_le16((u16) bytes); - - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, - HostCmd_ACT_GEN_GET, 0, &rd_eeprom); - - if (!ret) - memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); - return ret; -} - -/* - * This function sets a generic IE. In addition to generic IE, it can - * also handle WPA, WPA2 and WAPI IEs. - */ -static int -mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, - u16 ie_len) -{ - int ret = 0; - struct ieee_types_vendor_header *pvendor_ie; - const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 }; - const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 }; - - /* If the passed length is zero, reset the buffer */ - if (!ie_len) { - priv->gen_ie_buf_len = 0; - priv->wps.session_enable = false; - - return 0; - } else if (!ie_data_ptr) { - return -1; - } - pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; - /* Test to see if it is a WPA IE, if not, then it is a gen IE */ - if (((pvendor_ie->element_id == WLAN_EID_WPA) - && (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) - || (pvendor_ie->element_id == WLAN_EID_RSN)) { - - /* IE is a WPA/WPA2 IE so call set_wpa function */ - ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len); - priv->wps.session_enable = false; - - return ret; - } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) { - /* IE is a WAPI IE so call set_wapi function */ - ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len); - - return ret; - } - /* - * Verify that the passed length is not larger than the - * available space remaining in the buffer - */ - if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) { - - /* Test to see if it is a WPS IE, if so, enable - * wps session flag - */ - pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; - if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) - && (!memcmp(pvendor_ie->oui, wps_oui, - sizeof(wps_oui)))) { - priv->wps.session_enable = true; - dev_dbg(priv->adapter->dev, - "info: WPS Session Enabled.\n"); - } - - /* Append the passed data to the end of the - genIeBuffer */ - memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr, - ie_len); - /* Increment the stored buffer length by the - size passed */ - priv->gen_ie_buf_len += ie_len; - } else { - /* Passed data does not fit in the remaining - buffer space */ - ret = -1; - } - - /* Return 0, or -1 for error case */ - return ret; -} - -/* - * IOCTL request handler to set/get generic IE. - * - * In addition to various generic IEs, this function can also be - * used to set the ARP filter. - */ -static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, - struct mwifiex_ds_misc_gen_ie *gen_ie, - u16 action) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - switch (gen_ie->type) { - case MWIFIEX_IE_TYPE_GEN_IE: - if (action == HostCmd_ACT_GEN_GET) { - gen_ie->len = priv->wpa_ie_len; - memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len); - } else { - mwifiex_set_gen_ie_helper(priv, gen_ie->ie_data, - (u16) gen_ie->len); - } - break; - case MWIFIEX_IE_TYPE_ARP_FILTER: - memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter)); - if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) { - adapter->arp_filter_size = 0; - dev_err(adapter->dev, "invalid ARP filter size\n"); - return -1; - } else { - memcpy(adapter->arp_filter, gen_ie->ie_data, - gen_ie->len); - adapter->arp_filter_size = gen_ie->len; - } - break; - default: - dev_err(adapter->dev, "invalid IE type\n"); - return -1; - } - return 0; -} - -/* - * Sends IOCTL request to set a generic IE. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) -{ - struct mwifiex_ds_misc_gen_ie gen_ie; - - if (ie_len > IW_CUSTOM_MAX) - return -EFAULT; - - gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE; - gen_ie.len = ie_len; - memcpy(gen_ie.ie_data, ie, ie_len); - if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET)) - return -EFAULT; - - return 0; -} diff --git a/trunk/drivers/net/wireless/mwifiex/sta_rx.c b/trunk/drivers/net/wireless/mwifiex/sta_rx.c deleted file mode 100644 index 8282679e64fd..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sta_rx.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station RX data handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "11n_aggr.h" -#include "11n_rxreorder.h" - -/* - * This function processes the received packet and forwards it - * to kernel/upper layer. - * - * This function parses through the received packet and determines - * if it is a debug packet or normal packet. - * - * For non-debug packets, the function chops off unnecessary leading - * header bytes, reconstructs the packet as an ethernet frame or - * 802.2/llc/snap frame as required, and sends it to kernel/upper layer. - * - * The completion callback is called after processing in complete. - */ -int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - int ret = 0; - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; - struct rx_packet_hdr *rx_pkt_hdr; - struct rxpd *local_rx_pd; - int hdr_chop; - struct ethhdr *eth_hdr; - u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - local_rx_pd = (struct rxpd *) (skb->data); - - rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + - local_rx_pd->rx_pkt_offset); - - if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { - /* - * Replace the 803 header and rfc1042 header (llc/snap) with an - * EthernetII header, keep the src/dst and snap_type - * (ethertype). - * The firmware only passes up SNAP frames converting - * all RX Data from 802.11 to 802.2/LLC/SNAP frames. - * To create the Ethernet II, just move the src, dst address - * right before the snap_type. - */ - eth_hdr = (struct ethhdr *) - ((u8 *) &rx_pkt_hdr->eth803_hdr - + sizeof(rx_pkt_hdr->eth803_hdr) + - sizeof(rx_pkt_hdr->rfc1042_hdr) - - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) - - sizeof(rx_pkt_hdr->eth803_hdr.h_source) - - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); - - memcpy(eth_hdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, - sizeof(eth_hdr->h_source)); - memcpy(eth_hdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, - sizeof(eth_hdr->h_dest)); - - /* Chop off the rxpd + the excess memory from the 802.2/llc/snap - header that was removed. */ - hdr_chop = (u8 *) eth_hdr - (u8 *) local_rx_pd; - } else { - /* Chop off the rxpd */ - hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr - - (u8 *) local_rx_pd; - } - - /* Chop off the leading header bytes so the it points to the start of - either the reconstructed EthII frame or the 802.2/llc/snap frame */ - skb_pull(skb, hdr_chop); - - priv->rxpd_rate = local_rx_pd->rx_rate; - - priv->rxpd_htinfo = local_rx_pd->ht_info; - - ret = mwifiex_recv_packet(adapter, skb); - if (ret == -1) - dev_err(adapter->dev, "recv packet failed\n"); - - return ret; -} - -/* - * This function processes the received buffer. - * - * The function looks into the RxPD and performs sanity tests on the - * received buffer to ensure its a valid packet, before processing it - * further. If the packet is determined to be aggregated, it is - * de-aggregated accordingly. Non-unicast packets are sent directly to - * the kernel/upper layers. Unicast packets are handed over to the - * Rx reordering routine if 11n is enabled. - * - * The completion callback is called after processing in complete. - */ -int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - int ret = 0; - struct rxpd *local_rx_pd; - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - struct rx_packet_hdr *rx_pkt_hdr; - u8 ta[ETH_ALEN]; - u16 rx_pkt_type = 0; - struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; - - local_rx_pd = (struct rxpd *) (skb->data); - rx_pkt_type = local_rx_pd->rx_pkt_type; - - rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + - local_rx_pd->rx_pkt_offset); - - if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) > - (u16) skb->len) { - dev_err(adapter->dev, "wrong rx packet: len=%d," - " rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, - local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length); - priv->stats.rx_dropped++; - dev_kfree_skb_any(skb); - return ret; - } - if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { - mwifiex_11n_deaggregate_pkt(priv, skb); - return ret; - } - /* - * If the packet is not an unicast packet then send the packet - * directly to os. Don't pass thru rx reordering - */ - if (!IS_11N_ENABLED(priv) || - memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) { - mwifiex_process_rx_packet(adapter, skb); - return ret; - } - - if (mwifiex_queuing_ra_based(priv)) { - memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); - } else { - if (rx_pkt_type != PKT_TYPE_BAR) - priv->rx_seq[local_rx_pd->priority] = - local_rx_pd->seq_num; - memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, - ETH_ALEN); - } - - /* Reorder and send to OS */ - ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num, - local_rx_pd->priority, ta, - (u8) local_rx_pd->rx_pkt_type, - (void *) skb); - - if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { - if (priv && (ret == -1)) - priv->stats.rx_dropped++; - - dev_kfree_skb_any(skb); - } - - return ret; -} diff --git a/trunk/drivers/net/wireless/mwifiex/sta_tx.c b/trunk/drivers/net/wireless/mwifiex/sta_tx.c deleted file mode 100644 index 5d37ef160121..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/sta_tx.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station TX data handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" - -/* - * This function fills the TxPD for tx packets. - * - * The Tx buffer received by this function should already have the - * header space allocated for TxPD. - * - * This function inserts the TxPD in between interface header and actual - * data and adjusts the buffer pointers accordingly. - * - * The following TxPD fields are set by this function, as required - - * - BSS number - * - Tx packet length and offset - * - Priority - * - Packet delay - * - Priority specific Tx control - * - Flags - */ -void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct txpd *local_tx_pd; - struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - - if (!skb->len) { - dev_err(adapter->dev, "Tx: bad packet length: %d\n", - skb->len); - tx_info->status_code = -1; - return skb->data; - } - - BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN)); - skb_push(skb, sizeof(*local_tx_pd)); - - local_tx_pd = (struct txpd *) skb->data; - memset(local_tx_pd, 0, sizeof(struct txpd)); - local_tx_pd->bss_num = priv->bss_num; - local_tx_pd->bss_type = priv->bss_type; - local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len - - sizeof(struct txpd))); - - local_tx_pd->priority = (u8) skb->priority; - local_tx_pd->pkt_delay_2ms = - mwifiex_wmm_compute_drv_pkt_delay(priv, skb); - - if (local_tx_pd->priority < - ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) - /* - * Set the priority specific tx_control field, setting of 0 will - * cause the default value to be used later in this function - */ - local_tx_pd->tx_control = - cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd-> - priority]); - - if (adapter->pps_uapsd_mode) { - if (mwifiex_check_last_packet_indication(priv)) { - adapter->tx_lock_flag = true; - local_tx_pd->flags = - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; - } - } - - /* Offset of actual data */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); - - /* make space for INTF_HEADER_LEN */ - skb_push(skb, INTF_HEADER_LEN); - - if (!local_tx_pd->tx_control) - /* TxCtrl set by user or default */ - local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - return skb->data; -} - -/* - * This function tells firmware to send a NULL data packet. - * - * The function creates a NULL data packet with TxPD and sends to the - * firmware for transmission, with highest priority setting. - */ -int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct txpd *local_tx_pd; -/* sizeof(struct txpd) + Interface specific header */ -#define NULL_PACKET_HDR 64 - u32 data_len = NULL_PACKET_HDR; - struct sk_buff *skb = NULL; - int ret = 0; - struct mwifiex_txinfo *tx_info = NULL; - - if (adapter->surprise_removed) - return -1; - - if (!priv->media_connected) - return -1; - - if (adapter->data_sent) - return -1; - - skb = dev_alloc_skb(data_len); - if (!skb) - return -1; - - tx_info = MWIFIEX_SKB_TXCB(skb); - tx_info->bss_index = priv->bss_index; - skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN); - skb_push(skb, sizeof(struct txpd)); - - local_tx_pd = (struct txpd *) skb->data; - local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - local_tx_pd->flags = flags; - local_tx_pd->priority = WMM_HIGHEST_PRIORITY; - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); - local_tx_pd->bss_num = priv->bss_num; - local_tx_pd->bss_type = priv->bss_type; - - skb_push(skb, INTF_HEADER_LEN); - - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb->data, skb->len, NULL); - switch (ret) { - case -EBUSY: - adapter->data_sent = true; - /* Fall through FAILURE handling */ - case -1: - dev_kfree_skb_any(skb); - dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", - __func__, ret); - adapter->dbg.num_tx_host_to_card_failure++; - break; - case 0: - dev_kfree_skb_any(skb); - dev_dbg(adapter->dev, "data: %s: host_to_card succeeded\n", - __func__); - adapter->tx_lock_flag = true; - break; - case -EINPROGRESS: - break; - default: - break; - } - - return ret; -} - -/* - * This function checks if we need to send last packet indication. - */ -u8 -mwifiex_check_last_packet_indication(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 ret = false; - - if (!adapter->sleep_period.period) - return ret; - if (mwifiex_wmm_lists_empty(adapter)) - ret = true; - - if (ret && !adapter->cmd_sent && !adapter->curr_cmd - && !is_command_pending(adapter)) { - adapter->delay_null_pkt = false; - ret = true; - } else { - ret = false; - adapter->delay_null_pkt = true; - } - return ret; -} diff --git a/trunk/drivers/net/wireless/mwifiex/txrx.c b/trunk/drivers/net/wireless/mwifiex/txrx.c deleted file mode 100644 index ce772e078db8..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/txrx.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Marvell Wireless LAN device driver: generic TX/RX data handling - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" - -/* - * This function processes the received buffer. - * - * Main responsibility of this function is to parse the RxPD to - * identify the correct interface this packet is headed for and - * forwarding it to the associated handling function, where the - * packet will be further processed and sent to kernel/upper layer - * if required. - */ -int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - struct rxpd *local_rx_pd; - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - - local_rx_pd = (struct rxpd *) (skb->data); - /* Get the BSS number from rxpd, get corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num & - BSS_NUM_MASK, local_rx_pd->bss_type); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - rx_info->bss_index = priv->bss_index; - - return mwifiex_process_sta_rx_packet(adapter, skb); -} -EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); - -/* - * This function sends a packet to device. - * - * It processes the packet to add the TxPD, checks condition and - * sends the processed packet to firmware for transmission. - * - * On successful completion, the function calls the completion callback - * and logs the time. - */ -int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - int ret = -1; - struct mwifiex_adapter *adapter = priv->adapter; - u8 *head_ptr = NULL; - struct txpd *local_tx_pd = NULL; - - head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); - if (head_ptr) { - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - local_tx_pd = - (struct txpd *) (head_ptr + INTF_HEADER_LEN); - - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb->data, skb->len, tx_param); - } - - switch (ret) { - case -EBUSY: - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - (adapter->pps_uapsd_mode) && - (adapter->tx_lock_flag)) { - priv->adapter->tx_lock_flag = false; - local_tx_pd->flags = 0; - } - dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); - break; - case -1: - adapter->data_sent = false; - dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", - ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb, ret); - break; - case -EINPROGRESS: - adapter->data_sent = false; - break; - case 0: - mwifiex_write_data_complete(adapter, skb, ret); - break; - default: - break; - } - - return ret; -} - -/* - * Packet send completion callback handler. - * - * It either frees the buffer directly or forwards it to another - * completion callback which checks conditions, updates statistics, - * wakes up stalled traffic queue if required, and then frees the buffer. - */ -int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int status) -{ - struct mwifiex_private *priv = NULL, *tpriv = NULL; - struct mwifiex_txinfo *tx_info = NULL; - int i; - - if (!skb) - return 0; - - tx_info = MWIFIEX_SKB_TXCB(skb); - priv = mwifiex_bss_index_to_priv(adapter, tx_info->bss_index); - if (!priv) - goto done; - - priv->netdev->trans_start = jiffies; - if (!status) { - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; - } else { - priv->stats.tx_errors++; - } - atomic_dec(&adapter->tx_pending); - - for (i = 0; i < adapter->priv_num; i++) { - - tpriv = adapter->priv[i]; - - if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) - && (tpriv->media_connected)) { - if (netif_queue_stopped(tpriv->netdev)) - netif_wake_queue(tpriv->netdev); - } - } -done: - dev_kfree_skb_any(skb); - - return 0; -} - -/* - * Packet receive completion callback handler. - * - * This function calls another completion callback handler which - * updates the statistics, and optionally updates the parent buffer - * use count before freeing the received packet. - */ -int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int status) -{ - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - struct mwifiex_rxinfo *rx_info_parent = NULL; - struct mwifiex_private *priv; - struct sk_buff *skb_parent = NULL; - unsigned long flags; - - priv = adapter->priv[rx_info->bss_index]; - - if (priv && (status == -1)) - priv->stats.rx_dropped++; - - if (rx_info->parent) { - skb_parent = rx_info->parent; - rx_info_parent = MWIFIEX_SKB_RXCB(skb_parent); - - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - --rx_info_parent->use_count; - - if (!rx_info_parent->use_count) { - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - dev_kfree_skb_any(skb_parent); - } else { - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - } - } else { - dev_kfree_skb_any(skb); - } - - return 0; -} diff --git a/trunk/drivers/net/wireless/mwifiex/util.c b/trunk/drivers/net/wireless/mwifiex/util.c deleted file mode 100644 index 7ab4fb279f8a..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/util.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Marvell Wireless LAN device driver: utility functions - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * Firmware initialization complete callback handler. - * - * This function wakes up the function waiting on the init - * wait queue for the firmware initialization to complete. - */ -int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter) -{ - - adapter->init_wait_q_woken = true; - wake_up_interruptible(&adapter->init_wait_q); - return 0; -} - -/* - * Firmware shutdown complete callback handler. - * - * This function sets the hardware status to not ready and wakes up - * the function waiting on the init wait queue for the firmware - * shutdown to complete. - */ -int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) -{ - adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY; - adapter->init_wait_q_woken = true; - wake_up_interruptible(&adapter->init_wait_q); - return 0; -} - -/* - * This function sends init/shutdown command - * to firmware. - */ -int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, - u32 func_init_shutdown) -{ - u16 cmd; - - if (func_init_shutdown == MWIFIEX_FUNC_INIT) { - cmd = HostCmd_CMD_FUNC_INIT; - } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) { - cmd = HostCmd_CMD_FUNC_SHUTDOWN; - } else { - dev_err(priv->adapter->dev, "unsupported parameter\n"); - return -1; - } - - return mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL); -} -EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw); - -/* - * IOCTL request handler to set/get debug information. - * - * This function collates/sets the information from/to different driver - * structures. - */ -int mwifiex_get_debug_info(struct mwifiex_private *priv, - struct mwifiex_debug_info *info) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - if (info) { - memcpy(info->packets_out, - priv->wmm.packets_out, - sizeof(priv->wmm.packets_out)); - info->max_tx_buf_size = (u32) adapter->max_tx_buf_size; - info->tx_buf_size = (u32) adapter->tx_buf_size; - info->rx_tbl_num = mwifiex_get_rx_reorder_tbl( - priv, info->rx_tbl); - info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl( - priv, info->tx_tbl); - info->ps_mode = adapter->ps_mode; - info->ps_state = adapter->ps_state; - info->is_deep_sleep = adapter->is_deep_sleep; - info->pm_wakeup_card_req = adapter->pm_wakeup_card_req; - info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try; - info->is_hs_configured = adapter->is_hs_configured; - info->hs_activated = adapter->hs_activated; - info->num_cmd_host_to_card_failure - = adapter->dbg.num_cmd_host_to_card_failure; - info->num_cmd_sleep_cfm_host_to_card_failure - = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure; - info->num_tx_host_to_card_failure - = adapter->dbg.num_tx_host_to_card_failure; - info->num_event_deauth = adapter->dbg.num_event_deauth; - info->num_event_disassoc = adapter->dbg.num_event_disassoc; - info->num_event_link_lost = adapter->dbg.num_event_link_lost; - info->num_cmd_deauth = adapter->dbg.num_cmd_deauth; - info->num_cmd_assoc_success = - adapter->dbg.num_cmd_assoc_success; - info->num_cmd_assoc_failure = - adapter->dbg.num_cmd_assoc_failure; - info->num_tx_timeout = adapter->dbg.num_tx_timeout; - info->num_cmd_timeout = adapter->dbg.num_cmd_timeout; - info->timeout_cmd_id = adapter->dbg.timeout_cmd_id; - info->timeout_cmd_act = adapter->dbg.timeout_cmd_act; - memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, - sizeof(adapter->dbg.last_cmd_id)); - memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act, - sizeof(adapter->dbg.last_cmd_act)); - info->last_cmd_index = adapter->dbg.last_cmd_index; - memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id, - sizeof(adapter->dbg.last_cmd_resp_id)); - info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index; - memcpy(info->last_event, adapter->dbg.last_event, - sizeof(adapter->dbg.last_event)); - info->last_event_index = adapter->dbg.last_event_index; - info->data_sent = adapter->data_sent; - info->cmd_sent = adapter->cmd_sent; - info->cmd_resp_received = adapter->cmd_resp_received; - } - - return 0; -} - -/* - * This function processes the received packet before sending it to the - * kernel. - * - * It extracts the SKB from the received buffer and sends it to kernel. - * In case the received buffer does not contain the data in SKB format, - * the function creates a blank SKB, fills it with the data from the - * received buffer and then sends this new SKB to the kernel. - */ -int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) -{ - struct mwifiex_rxinfo *rx_info = NULL; - struct mwifiex_private *priv = NULL; - - if (!skb) - return -1; - - rx_info = MWIFIEX_SKB_RXCB(skb); - priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); - if (!priv) - return -1; - - skb->dev = priv->netdev; - skb->protocol = eth_type_trans(skb, priv->netdev); - skb->ip_summed = CHECKSUM_NONE; - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; - if (in_interrupt()) - netif_rx(skb); - else - netif_rx_ni(skb); - - return 0; -} - -/* - * Receive packet completion callback handler. - * - * This function updates the statistics and frees the buffer SKB. - */ -int mwifiex_recv_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int status) -{ - struct mwifiex_private *priv = NULL; - struct mwifiex_rxinfo *rx_info = NULL; - - if (!skb) - return 0; - - rx_info = MWIFIEX_SKB_RXCB(skb); - priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); - - if (priv && (status == -1)) - priv->stats.rx_dropped++; - - dev_kfree_skb_any(skb); - - return 0; -} - -/* - * IOCTL completion callback handler. - * - * This function is called when a pending IOCTL is completed. - * - * If work queue support is enabled, the function wakes up the - * corresponding waiting function. Otherwise, it processes the - * IOCTL response and frees the response buffer. - */ -int mwifiex_complete_cmd(struct mwifiex_adapter *adapter) -{ - atomic_dec(&adapter->cmd_pending); - dev_dbg(adapter->dev, "cmd completed: status=%d\n", - adapter->cmd_wait_q.status); - - adapter->cmd_wait_q.condition = true; - - if (adapter->cmd_wait_q.status == -ETIMEDOUT) - dev_err(adapter->dev, "cmd timeout\n"); - else - wake_up_interruptible(&adapter->cmd_wait_q.wait); - - return 0; -} diff --git a/trunk/drivers/net/wireless/mwifiex/util.h b/trunk/drivers/net/wireless/mwifiex/util.h deleted file mode 100644 index 9506afc6c0e4..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/util.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Marvell Wireless LAN device driver: utility functions - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_UTIL_H_ -#define _MWIFIEX_UTIL_H_ - -static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) -{ - return (struct mwifiex_rxinfo *)skb->cb; -} - -static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) -{ - return (struct mwifiex_txinfo *)skb->cb; -} -#endif /* !_MWIFIEX_UTIL_H_ */ diff --git a/trunk/drivers/net/wireless/mwifiex/wmm.c b/trunk/drivers/net/wireless/mwifiex/wmm.c deleted file mode 100644 index c009370f309e..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/wmm.c +++ /dev/null @@ -1,1231 +0,0 @@ -/* - * Marvell Wireless LAN device driver: WMM - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - - -/* Maximum value FW can accept for driver delay in packet transmission */ -#define DRV_PKT_DELAY_TO_FW_MAX 512 - - -#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 - -#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 - -/* Offset for TOS field in the IP header */ -#define IPTOS_OFFSET 5 - -/* WMM information IE */ -static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, - 0x00, 0x50, 0xf2, 0x02, - 0x00, 0x01, 0x00 -}; - -static const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, - WMM_AC_BK, - WMM_AC_VI, - WMM_AC_VO -}; - -static u8 tos_to_tid[] = { - /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ - 0x01, /* 0 1 0 AC_BK */ - 0x02, /* 0 0 0 AC_BK */ - 0x00, /* 0 0 1 AC_BE */ - 0x03, /* 0 1 1 AC_BE */ - 0x04, /* 1 0 0 AC_VI */ - 0x05, /* 1 0 1 AC_VI */ - 0x06, /* 1 1 0 AC_VO */ - 0x07 /* 1 1 1 AC_VO */ -}; - -/* - * This table inverses the tos_to_tid operation to get a priority - * which is in sequential order, and can be compared. - * Use this to compare the priority of two different TIDs. - */ -static u8 tos_to_tid_inv[] = { - 0x02, /* from tos_to_tid[2] = 0 */ - 0x00, /* from tos_to_tid[0] = 1 */ - 0x01, /* from tos_to_tid[1] = 2 */ - 0x03, - 0x04, - 0x05, - 0x06, - 0x07}; - -static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; - -/* - * This function debug prints the priority parameters for a WMM AC. - */ -static void -mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param) -{ - const char *ac_str[] = { "BK", "BE", "VI", "VO" }; - - pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " - "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", - ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap - & MWIFIEX_ACI) >> 5]], - (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5, - (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4, - ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN, - ac_param->ecw_bitmap & MWIFIEX_ECW_MIN, - (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4, - le16_to_cpu(ac_param->tx_op_limit)); -} - -/* - * This function allocates a route address list. - * - * The function also initializes the list with the provided RA. - */ -static struct mwifiex_ra_list_tbl * -mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) -{ - struct mwifiex_ra_list_tbl *ra_list; - - ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC); - - if (!ra_list) { - dev_err(adapter->dev, "%s: failed to alloc ra_list\n", - __func__); - return NULL; - } - INIT_LIST_HEAD(&ra_list->list); - skb_queue_head_init(&ra_list->skb_head); - - memcpy(ra_list->ra, ra, ETH_ALEN); - - ra_list->total_pkts_size = 0; - - dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); - - return ra_list; -} - -/* - * This function allocates and adds a RA list for all TIDs - * with the given RA. - */ -void -mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) -{ - int i; - struct mwifiex_ra_list_tbl *ra_list; - struct mwifiex_adapter *adapter = priv->adapter; - - for (i = 0; i < MAX_NUM_TID; ++i) { - ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); - dev_dbg(adapter->dev, "info: created ra_list %p\n", ra_list); - - if (!ra_list) - break; - - if (!mwifiex_queuing_ra_based(priv)) - ra_list->is_11n_enabled = IS_11N_ENABLED(priv); - else - ra_list->is_11n_enabled = false; - - dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n", - ra_list, ra_list->is_11n_enabled); - - list_add_tail(&ra_list->list, - &priv->wmm.tid_tbl_ptr[i].ra_list); - - if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr) - priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list; - } -} - -/* - * This function sets the WMM queue priorities to their default values. - */ -static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) -{ - /* Default queue priorities: VO->VI->BE->BK */ - priv->wmm.queue_priority[0] = WMM_AC_VO; - priv->wmm.queue_priority[1] = WMM_AC_VI; - priv->wmm.queue_priority[2] = WMM_AC_BE; - priv->wmm.queue_priority[3] = WMM_AC_BK; -} - -/* - * This function map ACs to TIDs. - */ -static void -mwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) -{ - int i; - - for (i = 0; i < 4; ++i) { - tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; - tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; - } -} - -/* - * This function initializes WMM priority queues. - */ -void -mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, - struct ieee_types_wmm_parameter *wmm_ie) -{ - u16 cw_min, avg_back_off, tmp[4]; - u32 i, j, num_ac; - u8 ac_idx; - - if (!wmm_ie || !priv->wmm_enabled) { - /* WMM is not enabled, just set the defaults and return */ - mwifiex_wmm_default_queue_priorities(priv); - return; - } - - dev_dbg(priv->adapter->dev, "info: WMM Parameter IE: version=%d, " - "qos_info Parameter Set Count=%d, Reserved=%#x\n", - wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & - IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, - wmm_ie->reserved); - - for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { - cw_min = (1 << (wmm_ie->ac_params[num_ac].ecw_bitmap & - MWIFIEX_ECW_MIN)) - 1; - avg_back_off = (cw_min >> 1) + - (wmm_ie->ac_params[num_ac].aci_aifsn_bitmap & - MWIFIEX_AIFSN); - - ac_idx = wmm_aci_to_qidx_map[(wmm_ie->ac_params[num_ac]. - aci_aifsn_bitmap & - MWIFIEX_ACI) >> 5]; - priv->wmm.queue_priority[ac_idx] = ac_idx; - tmp[ac_idx] = avg_back_off; - - dev_dbg(priv->adapter->dev, "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", - (1 << ((wmm_ie->ac_params[num_ac].ecw_bitmap & - MWIFIEX_ECW_MAX) >> 4)) - 1, - cw_min, avg_back_off); - mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); - } - - /* Bubble sort */ - for (i = 0; i < num_ac; i++) { - for (j = 1; j < num_ac - i; j++) { - if (tmp[j - 1] > tmp[j]) { - swap(tmp[j - 1], tmp[j]); - swap(priv->wmm.queue_priority[j - 1], - priv->wmm.queue_priority[j]); - } else if (tmp[j - 1] == tmp[j]) { - if (priv->wmm.queue_priority[j - 1] - < priv->wmm.queue_priority[j]) - swap(priv->wmm.queue_priority[j - 1], - priv->wmm.queue_priority[j]); - } - } - } - - mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); -} - -/* - * This function evaluates whether or not an AC is to be downgraded. - * - * In case the AC is not enabled, the highest AC is returned that is - * enabled and does not require admission control. - */ -static enum mwifiex_wmm_ac_e -mwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv, - enum mwifiex_wmm_ac_e eval_ac) -{ - int down_ac; - enum mwifiex_wmm_ac_e ret_ac; - struct mwifiex_wmm_ac_status *ac_status; - - ac_status = &priv->wmm.ac_status[eval_ac]; - - if (!ac_status->disabled) - /* Okay to use this AC, its enabled */ - return eval_ac; - - /* Setup a default return value of the lowest priority */ - ret_ac = WMM_AC_BK; - - /* - * Find the highest AC that is enabled and does not require - * admission control. The spec disallows downgrading to an AC, - * which is enabled due to a completed admission control. - * Unadmitted traffic is not to be sent on an AC with admitted - * traffic. - */ - for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { - ac_status = &priv->wmm.ac_status[down_ac]; - - if (!ac_status->disabled && !ac_status->flow_required) - /* AC is enabled and does not require admission - control */ - ret_ac = (enum mwifiex_wmm_ac_e) down_ac; - } - - return ret_ac; -} - -/* - * This function downgrades WMM priority queue. - */ -void -mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv) -{ - int ac_val; - - dev_dbg(priv->adapter->dev, "info: WMM: AC Priorities:" - "BK(0), BE(1), VI(2), VO(3)\n"); - - if (!priv->wmm_enabled) { - /* WMM is not enabled, default priorities */ - for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) - priv->wmm.ac_down_graded_vals[ac_val] = - (enum mwifiex_wmm_ac_e) ac_val; - } else { - for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { - priv->wmm.ac_down_graded_vals[ac_val] - = mwifiex_wmm_eval_downgrade_ac(priv, - (enum mwifiex_wmm_ac_e) ac_val); - dev_dbg(priv->adapter->dev, "info: WMM: AC PRIO %d maps to %d\n", - ac_val, priv->wmm.ac_down_graded_vals[ac_val]); - } - } -} - -/* - * This function converts the IP TOS field to an WMM AC - * Queue assignment. - */ -static enum mwifiex_wmm_ac_e -mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) -{ - /* Map of TOS UP values to WMM AC */ - const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, - WMM_AC_BK, - WMM_AC_BK, - WMM_AC_BE, - WMM_AC_VI, - WMM_AC_VI, - WMM_AC_VO, - WMM_AC_VO - }; - - if (tos >= ARRAY_SIZE(tos_to_ac)) - return WMM_AC_BE; - - return tos_to_ac[tos]; -} - -/* - * This function evaluates a given TID and downgrades it to a lower - * TID if the WMM Parameter IE received from the AP indicates that the - * AP is disabled (due to call admission control (ACM bit). Mapping - * of TID to AC is taken care of internally. - */ -static u8 -mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) -{ - enum mwifiex_wmm_ac_e ac, ac_down; - u8 new_tid; - - ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid); - ac_down = priv->wmm.ac_down_graded_vals[ac]; - - /* Send the index to tid array, picking from the array will be - * taken care by dequeuing function - */ - new_tid = ac_to_tid[ac_down][tid % 2]; - - return new_tid; -} - -/* - * This function initializes the WMM state information and the - * WMM data path queues. - */ -void -mwifiex_wmm_init(struct mwifiex_adapter *adapter) -{ - int i, j; - struct mwifiex_private *priv; - - for (j = 0; j < adapter->priv_num; ++j) { - priv = adapter->priv[j]; - if (!priv) - continue; - - for (i = 0; i < MAX_NUM_TID; ++i) { - priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; - priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; - priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; - priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; - } - - priv->aggr_prio_tbl[6].amsdu - = priv->aggr_prio_tbl[6].ampdu_ap - = priv->aggr_prio_tbl[6].ampdu_user - = BA_STREAM_NOT_ALLOWED; - - priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap - = priv->aggr_prio_tbl[7].ampdu_user - = BA_STREAM_NOT_ALLOWED; - - priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; - priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; - priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; - } -} - -/* - * This function checks if WMM Tx queue is empty. - */ -int -mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) -{ - int i, j; - struct mwifiex_private *priv; - - for (j = 0; j < adapter->priv_num; ++j) { - priv = adapter->priv[j]; - if (priv) { - for (i = 0; i < MAX_NUM_TID; i++) - if (!mwifiex_wmm_is_ra_list_empty( - &priv->wmm.tid_tbl_ptr[i].ra_list)) - return false; - } - } - - return true; -} - -/* - * This function deletes all packets in an RA list node. - * - * The packet sent completion callback handler are called with - * status failure, after they are dequeued to ensure proper - * cleanup. The RA list node itself is freed at the end. - */ -static void -mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra_list) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct sk_buff *skb, *tmp; - - skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) - mwifiex_write_data_complete(adapter, skb, -1); -} - -/* - * This function deletes all packets in an RA list. - * - * Each nodes in the RA list are freed individually first, and then - * the RA list itself is freed. - */ -static void -mwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv, - struct list_head *ra_list_head) -{ - struct mwifiex_ra_list_tbl *ra_list; - - list_for_each_entry(ra_list, ra_list_head, list) - mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); -} - -/* - * This function deletes all packets in all RA lists. - */ -static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) -{ - int i; - - for (i = 0; i < MAX_NUM_TID; i++) - mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. - ra_list); -} - -/* - * This function deletes all route addresses from all RA lists. - */ -static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) -{ - struct mwifiex_ra_list_tbl *ra_list, *tmp_node; - int i; - - for (i = 0; i < MAX_NUM_TID; ++i) { - dev_dbg(priv->adapter->dev, - "info: ra_list: freeing buf for tid %d\n", i); - list_for_each_entry_safe(ra_list, tmp_node, - &priv->wmm.tid_tbl_ptr[i].ra_list, list) { - list_del(&ra_list->list); - kfree(ra_list); - } - - INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); - - priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; - } -} - -/* - * This function cleans up the Tx and Rx queues. - * - * Cleanup includes - - * - All packets in RA lists - * - All entries in Rx reorder table - * - All entries in Tx BA stream table - * - MPA buffer (if required) - * - All RA lists - */ -void -mwifiex_clean_txrx(struct mwifiex_private *priv) -{ - unsigned long flags; - - mwifiex_11n_cleanup_reorder_tbl(priv); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - mwifiex_wmm_cleanup_queues(priv); - mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); - - if (priv->adapter->if_ops.cleanup_mpa_buf) - priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); - - mwifiex_wmm_delete_all_ralist(priv); - memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* - * This function retrieves a particular RA list node, matching with the - * given TID and RA address. - */ -static struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, - u8 *ra_addr) -{ - struct mwifiex_ra_list_tbl *ra_list; - - list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, - list) { - if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) - return ra_list; - } - - return NULL; -} - -/* - * This function retrieves an RA list node for a given TID and - * RA address pair. - * - * If no such node is found, a new node is added first and then - * retrieved. - */ -static struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) -{ - struct mwifiex_ra_list_tbl *ra_list; - - ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); - if (ra_list) - return ra_list; - mwifiex_ralist_add(priv, ra_addr); - - return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); -} - -/* - * This function checks if a particular RA list node exists in a given TID - * table index. - */ -int -mwifiex_is_ralist_valid(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra_list, int ptr_index) -{ - struct mwifiex_ra_list_tbl *rlist; - - list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, - list) { - if (rlist == ra_list) - return true; - } - - return false; -} - -/* - * This function adds a packet to WMM queue. - * - * In disconnected state the packet is immediately dropped and the - * packet send completion callback is called with status failure. - * - * Otherwise, the correct RA list node is located and the packet - * is queued at the list tail. - */ -void -mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - struct mwifiex_private *priv = adapter->priv[tx_info->bss_index]; - u32 tid; - struct mwifiex_ra_list_tbl *ra_list; - u8 ra[ETH_ALEN], tid_down; - unsigned long flags; - - if (!priv->media_connected) { - dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); - mwifiex_write_data_complete(adapter, skb, -1); - return; - } - - tid = skb->priority; - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - tid_down = mwifiex_wmm_downgrade_tid(priv, tid); - - /* In case of infra as we have already created the list during - association we just don't have to call get_queue_raptr, we will - have only 1 raptr for a tid in case of infra */ - if (!mwifiex_queuing_ra_based(priv)) { - if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) - ra_list = list_first_entry( - &priv->wmm.tid_tbl_ptr[tid_down].ra_list, - struct mwifiex_ra_list_tbl, list); - else - ra_list = NULL; - } else { - memcpy(ra, skb->data, ETH_ALEN); - ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); - } - - if (!ra_list) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - mwifiex_write_data_complete(adapter, skb, -1); - return; - } - - skb_queue_tail(&ra_list->skb_head, skb); - - ra_list->total_pkts_size += skb->len; - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* - * This function processes the get WMM status command response from firmware. - * - * The response may contain multiple TLVs - - * - AC Queue status TLVs - * - Current WMM Parameter IE TLV - * - Admission Control action frame TLVs - * - * This function parses the TLVs and then calls further specific functions - * to process any changes in the queue prioritize or state. - */ -int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, - const struct host_cmd_ds_command *resp) -{ - u8 *curr = (u8 *) &resp->params.get_wmm_status; - uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; - int valid = true; - - struct mwifiex_ie_types_data *tlv_hdr; - struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; - struct ieee_types_wmm_parameter *wmm_param_ie = NULL; - struct mwifiex_wmm_ac_status *ac_status; - - dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", - resp_len); - - while ((resp_len >= sizeof(tlv_hdr->header)) && valid) { - tlv_hdr = (struct mwifiex_ie_types_data *) curr; - tlv_len = le16_to_cpu(tlv_hdr->header.len); - - switch (le16_to_cpu(tlv_hdr->header.type)) { - case TLV_TYPE_WMMQSTATUS: - tlv_wmm_qstatus = - (struct mwifiex_ie_types_wmm_queue_status *) - tlv_hdr; - dev_dbg(priv->adapter->dev, - "info: CMD_RESP: WMM_GET_STATUS:" - " QSTATUS TLV: %d, %d, %d\n", - tlv_wmm_qstatus->queue_index, - tlv_wmm_qstatus->flow_required, - tlv_wmm_qstatus->disabled); - - ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus-> - queue_index]; - ac_status->disabled = tlv_wmm_qstatus->disabled; - ac_status->flow_required = - tlv_wmm_qstatus->flow_required; - ac_status->flow_created = tlv_wmm_qstatus->flow_created; - break; - - case WLAN_EID_VENDOR_SPECIFIC: - /* - * Point the regular IEEE IE 2 bytes into the Marvell IE - * and setup the IEEE IE type and length byte fields - */ - - wmm_param_ie = - (struct ieee_types_wmm_parameter *) (curr + - 2); - wmm_param_ie->vend_hdr.len = (u8) tlv_len; - wmm_param_ie->vend_hdr.element_id = - WLAN_EID_VENDOR_SPECIFIC; - - dev_dbg(priv->adapter->dev, - "info: CMD_RESP: WMM_GET_STATUS:" - " WMM Parameter Set Count: %d\n", - wmm_param_ie->qos_info_bitmap & - IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK); - - memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. - wmm_ie, wmm_param_ie, - wmm_param_ie->vend_hdr.len + 2); - - break; - - default: - valid = false; - break; - } - - curr += (tlv_len + sizeof(tlv_hdr->header)); - resp_len -= (tlv_len + sizeof(tlv_hdr->header)); - } - - mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); - mwifiex_wmm_setup_ac_downgrade(priv); - - return 0; -} - -/* - * Callback handler from the command module to allow insertion of a WMM TLV. - * - * If the BSS we are associating to supports WMM, this function adds the - * required WMM Information IE to the association request command buffer in - * the form of a Marvell extended IEEE IE. - */ -u32 -mwifiex_wmm_process_association_req(struct mwifiex_private *priv, - u8 **assoc_buf, - struct ieee_types_wmm_parameter *wmm_ie, - struct ieee80211_ht_cap *ht_cap) -{ - struct mwifiex_ie_types_wmm_param_set *wmm_tlv; - u32 ret_len = 0; - - /* Null checks */ - if (!assoc_buf) - return 0; - if (!(*assoc_buf)) - return 0; - - if (!wmm_ie) - return 0; - - dev_dbg(priv->adapter->dev, "info: WMM: process assoc req:" - "bss->wmmIe=0x%x\n", - wmm_ie->vend_hdr.element_id); - - if ((priv->wmm_required - || (ht_cap && (priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN)) - ) - && wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) { - wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf; - wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]); - wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]); - memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], - le16_to_cpu(wmm_tlv->header.len)); - if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) - memcpy((u8 *) (wmm_tlv->wmm_ie - + le16_to_cpu(wmm_tlv->header.len) - - sizeof(priv->wmm_qosinfo)), - &priv->wmm_qosinfo, - sizeof(priv->wmm_qosinfo)); - - ret_len = sizeof(wmm_tlv->header) - + le16_to_cpu(wmm_tlv->header.len); - - *assoc_buf += ret_len; - } - - return ret_len; -} - -/* - * This function computes the time delay in the driver queues for a - * given packet. - * - * When the packet is received at the OS/Driver interface, the current - * time is set in the packet structure. The difference between the present - * time and that received time is computed in this function and limited - * based on pre-compiled limits in the driver. - */ -u8 -mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, - const struct sk_buff *skb) -{ - u8 ret_val = 0; - struct timeval out_tstamp, in_tstamp; - u32 queue_delay; - - do_gettimeofday(&out_tstamp); - in_tstamp = ktime_to_timeval(skb->tstamp); - - queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000; - queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000; - - /* - * Queue delay is passed as a uint8 in units of 2ms (ms shifted - * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. - * - * Pass max value if queue_delay is beyond the uint8 range - */ - ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); - - dev_dbg(priv->adapter->dev, "data: WMM: Pkt Delay: %d ms," - " %d ms sent to FW\n", queue_delay, ret_val); - - return ret_val; -} - -/* - * This function retrieves the highest priority RA list table pointer. - */ -static struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, - struct mwifiex_private **priv, int *tid) -{ - struct mwifiex_private *priv_tmp; - struct mwifiex_ra_list_tbl *ptr, *head; - struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; - struct mwifiex_tid_tbl *tid_ptr; - int is_list_empty; - unsigned long flags; - int i, j; - - for (j = adapter->priv_num - 1; j >= 0; --j) { - spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, - flags); - is_list_empty = list_empty(&adapter->bss_prio_tbl[j] - .bss_prio_head); - spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, - flags); - if (is_list_empty) - continue; - - if (adapter->bss_prio_tbl[j].bss_prio_cur == - (struct mwifiex_bss_prio_node *) - &adapter->bss_prio_tbl[j].bss_prio_head) { - bssprio_node = - list_first_entry(&adapter->bss_prio_tbl[j] - .bss_prio_head, - struct mwifiex_bss_prio_node, - list); - bssprio_head = bssprio_node; - } else { - bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; - bssprio_head = bssprio_node; - } - - do { - priv_tmp = bssprio_node->priv; - - for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { - - tid_ptr = &(priv_tmp)->wmm. - tid_tbl_ptr[tos_to_tid[i]]; - - spin_lock_irqsave(&tid_ptr->tid_tbl_lock, - flags); - is_list_empty = - list_empty(&adapter->bss_prio_tbl[j] - .bss_prio_head); - spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, - flags); - if (is_list_empty) - continue; - - /* - * Always choose the next ra we transmitted - * last time, this way we pick the ra's in - * round robin fashion. - */ - ptr = list_first_entry( - &tid_ptr->ra_list_curr->list, - struct mwifiex_ra_list_tbl, - list); - - head = ptr; - if (ptr == (struct mwifiex_ra_list_tbl *) - &tid_ptr->ra_list) { - /* Get next ra */ - ptr = list_first_entry(&ptr->list, - struct mwifiex_ra_list_tbl, list); - head = ptr; - } - - do { - is_list_empty = - skb_queue_empty(&ptr->skb_head); - if (!is_list_empty) { - *priv = priv_tmp; - *tid = tos_to_tid[i]; - return ptr; - } - /* Get next ra */ - ptr = list_first_entry(&ptr->list, - struct mwifiex_ra_list_tbl, - list); - if (ptr == - (struct mwifiex_ra_list_tbl *) - &tid_ptr->ra_list) - ptr = list_first_entry( - &ptr->list, - struct mwifiex_ra_list_tbl, - list); - } while (ptr != head); - } - - /* Get next bss priority node */ - bssprio_node = list_first_entry(&bssprio_node->list, - struct mwifiex_bss_prio_node, - list); - - if (bssprio_node == - (struct mwifiex_bss_prio_node *) - &adapter->bss_prio_tbl[j].bss_prio_head) - /* Get next bss priority node */ - bssprio_node = list_first_entry( - &bssprio_node->list, - struct mwifiex_bss_prio_node, - list); - } while (bssprio_node != bssprio_head); - } - return NULL; -} - -/* - * This function gets the number of packets in the Tx queue of a - * particular RA list. - */ -static int -mwifiex_num_pkts_in_txq(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int max_buf_size) -{ - int count = 0, total_size = 0; - struct sk_buff *skb, *tmp; - - skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { - total_size += skb->len; - if (total_size < max_buf_size) - ++count; - else - break; - } - - return count; -} - -/* - * This function sends a single packet to firmware for transmission. - */ -static void -mwifiex_send_single_packet(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_index, - unsigned long ra_list_flags) - __releases(&priv->wmm.ra_list_spinlock) -{ - struct sk_buff *skb, *skb_next; - struct mwifiex_tx_param tx_param; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_txinfo *tx_info; - - if (skb_queue_empty(&ptr->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - dev_dbg(adapter->dev, "data: nothing to send\n"); - return; - } - - skb = skb_dequeue(&ptr->skb_head); - - tx_info = MWIFIEX_SKB_TXCB(skb); - dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); - - ptr->total_pkts_size -= skb->len; - - if (!skb_queue_empty(&ptr->skb_head)) - skb_next = skb_peek(&ptr->skb_head); - else - skb_next = NULL; - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - - tx_param.next_pkt_len = ((skb_next) ? skb_next->len + - sizeof(struct txpd) : 0); - - if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { - /* Queue the packet back at the head */ - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_write_data_complete(adapter, skb, -1); - return; - } - - skb_queue_tail(&ptr->skb_head, skb); - - ptr->total_pkts_size += skb->len; - tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - } else { - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - priv->wmm.packets_out[ptr_index]++; - priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; - } - adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = - list_first_entry( - &adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_cur->list, - struct mwifiex_bss_prio_node, - list); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - } -} - -/* - * This function checks if the first packet in the given RA list - * is already processed or not. - */ -static int -mwifiex_is_ptr_processed(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr) -{ - struct sk_buff *skb; - struct mwifiex_txinfo *tx_info; - - if (skb_queue_empty(&ptr->skb_head)) - return false; - - skb = skb_peek(&ptr->skb_head); - - tx_info = MWIFIEX_SKB_TXCB(skb); - if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT) - return true; - - return false; -} - -/* - * This function sends a single processed packet to firmware for - * transmission. - */ -static void -mwifiex_send_processed_packet(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_index, - unsigned long ra_list_flags) - __releases(&priv->wmm.ra_list_spinlock) -{ - struct mwifiex_tx_param tx_param; - struct mwifiex_adapter *adapter = priv->adapter; - int ret = -1; - struct sk_buff *skb, *skb_next; - struct mwifiex_txinfo *tx_info; - - if (skb_queue_empty(&ptr->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return; - } - - skb = skb_dequeue(&ptr->skb_head); - - if (!skb_queue_empty(&ptr->skb_head)) - skb_next = skb_peek(&ptr->skb_head); - else - skb_next = NULL; - - tx_info = MWIFIEX_SKB_TXCB(skb); - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - tx_param.next_pkt_len = - ((skb_next) ? skb_next->len + - sizeof(struct txpd) : 0); - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb->data, skb->len, &tx_param); - switch (ret) { - case -EBUSY: - dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_write_data_complete(adapter, skb, -1); - return; - } - - skb_queue_tail(&ptr->skb_head, skb); - - tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - break; - case -1: - adapter->data_sent = false; - dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb, ret); - break; - case -EINPROGRESS: - adapter->data_sent = false; - default: - break; - } - if (ret != -EBUSY) { - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - priv->wmm.packets_out[ptr_index]++; - priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; - } - adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = - list_first_entry( - &adapter->bss_prio_tbl[priv->bss_priority] - .bss_prio_cur->list, - struct mwifiex_bss_prio_node, - list); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - } -} - -/* - * This function dequeues a packet from the highest priority list - * and transmits it. - */ -static int -mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) -{ - struct mwifiex_ra_list_tbl *ptr; - struct mwifiex_private *priv = NULL; - int ptr_index = 0; - u8 ra[ETH_ALEN]; - int tid_del = 0, tid = 0; - unsigned long flags; - - ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); - if (!ptr) - return -1; - - tid = mwifiex_get_tid(ptr); - - dev_dbg(adapter->dev, "data: tid=%d\n", tid); - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - return -1; - } - - if (mwifiex_is_ptr_processed(priv, ptr)) { - mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_send_processed_packet() */ - return 0; - } - - if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) - || ((priv->sec_info.wpa_enabled - || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set) - ) { - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_send_single_packet() */ - } else { - if (mwifiex_is_ampdu_allowed(priv, tid)) { - if (mwifiex_space_avail_for_new_ba_stream(adapter)) { - mwifiex_11n_create_tx_ba_stream_tbl(priv, - ptr->ra, tid, - BA_STREAM_SETUP_INPROGRESS); - mwifiex_send_addba(priv, tid, ptr->ra); - } else if (mwifiex_find_stream_to_delete - (priv, tid, &tid_del, ra)) { - mwifiex_11n_create_tx_ba_stream_tbl(priv, - ptr->ra, tid, - BA_STREAM_SETUP_INPROGRESS); - mwifiex_send_delba(priv, tid_del, ra, 1); - } - } -/* Minimum number of AMSDU */ -#define MIN_NUM_AMSDU 2 - if (mwifiex_is_amsdu_allowed(priv, tid) && - (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >= - MIN_NUM_AMSDU)) - mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, - ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_11n_aggregate_pkt() */ - else - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_send_single_packet() */ - } - return 0; -} - -/* - * This function transmits the highest priority packet awaiting in the - * WMM Queues. - */ -void -mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) -{ - do { - /* Check if busy */ - if (adapter->data_sent || adapter->tx_lock_flag) - break; - - if (mwifiex_dequeue_tx_packet(adapter)) - break; - } while (true); -} diff --git a/trunk/drivers/net/wireless/mwifiex/wmm.h b/trunk/drivers/net/wireless/mwifiex/wmm.h deleted file mode 100644 index fcea1f68792f..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/wmm.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Marvell Wireless LAN device driver: WMM - * - * Copyright (C) 2011, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_WMM_H_ -#define _MWIFIEX_WMM_H_ - -enum ieee_types_wmm_aciaifsn_bitmasks { - MWIFIEX_AIFSN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), - MWIFIEX_ACM = BIT(4), - MWIFIEX_ACI = (BIT(5) | BIT(6)), -}; - -enum ieee_types_wmm_ecw_bitmasks { - MWIFIEX_ECW_MIN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), - MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)), -}; - -/* - * This function retrieves the TID of the given RA list. - */ -static inline int -mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr) -{ - struct sk_buff *skb; - - if (skb_queue_empty(&ptr->skb_head)) - return 0; - - skb = skb_peek(&ptr->skb_head); - - return skb->priority; -} - -/* - * This function gets the length of a list. - */ -static inline int -mwifiex_wmm_list_len(struct list_head *head) -{ - struct list_head *pos; - int count = 0; - - list_for_each(pos, head) - ++count; - - return count; -} - -/* - * This function checks if a RA list is empty or not. - */ -static inline u8 -mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) -{ - struct mwifiex_ra_list_tbl *ra_list; - int is_list_empty; - - list_for_each_entry(ra_list, ra_list_hhead, list) { - is_list_empty = skb_queue_empty(&ra_list->skb_head); - if (!is_list_empty) - return false; - } - - return true; -} - -void mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, - struct sk_buff *skb); -void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); - -int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); -void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); -int mwifiex_is_ralist_valid(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra_list, int tid); - -u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, - const struct sk_buff *skb); -void mwifiex_wmm_init(struct mwifiex_adapter *adapter); - -extern u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv, - u8 **assoc_buf, - struct ieee_types_wmm_parameter - *wmmie, - struct ieee80211_ht_cap - *htcap); - -void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, - struct ieee_types_wmm_parameter - *wmm_ie); -void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); -extern int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, - const struct host_cmd_ds_command *resp); - -#endif /* !_MWIFIEX_WMM_H_ */ diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index 8a1b26255f03..c1ceb4b23971 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -63,7 +63,6 @@ MODULE_PARM_DESC(ap_mode_default, #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c #define MWL8K_A2H_INT_DUMMY (1 << 20) -#define MWL8K_A2H_INT_BA_WATCHDOG (1 << 14) #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) @@ -74,14 +73,6 @@ MODULE_PARM_DESC(ap_mode_default, #define MWL8K_A2H_INT_RX_READY (1 << 1) #define MWL8K_A2H_INT_TX_DONE (1 << 0) -/* HW micro second timer register - * located at offset 0xA600. This - * will be used to timestamp tx - * packets. - */ - -#define MWL8K_HW_TIMER_REGISTER 0x0000a600 - #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ MWL8K_A2H_INT_CHNL_SWITCHED | \ MWL8K_A2H_INT_QUEUE_EMPTY | \ @@ -91,14 +82,10 @@ MODULE_PARM_DESC(ap_mode_default, MWL8K_A2H_INT_MAC_EVENT | \ MWL8K_A2H_INT_OPC_DONE | \ MWL8K_A2H_INT_RX_READY | \ - MWL8K_A2H_INT_TX_DONE | \ - MWL8K_A2H_INT_BA_WATCHDOG) + MWL8K_A2H_INT_TX_DONE) #define MWL8K_RX_QUEUES 1 -#define MWL8K_TX_WMM_QUEUES 4 -#define MWL8K_MAX_AMPDU_QUEUES 8 -#define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES) -#define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues) +#define MWL8K_TX_QUEUES 4 struct rxd_ops { int rxd_size; @@ -147,21 +134,6 @@ struct mwl8k_tx_queue { struct sk_buff **skb; }; -enum { - AMPDU_NO_STREAM, - AMPDU_STREAM_NEW, - AMPDU_STREAM_IN_PROGRESS, - AMPDU_STREAM_ACTIVE, -}; - -struct mwl8k_ampdu_stream { - struct ieee80211_sta *sta; - u8 tid; - u8 state; - u8 idx; - u8 txq_idx; /* index of this stream in priv->txq */ -}; - struct mwl8k_priv { struct ieee80211_hw *hw; struct pci_dev *pdev; @@ -188,12 +160,6 @@ struct mwl8k_priv { u32 ap_macids_supported; u32 sta_macids_supported; - /* Ampdu stream information */ - u8 num_ampdu_queues; - spinlock_t stream_lock; - struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES]; - struct work_struct watchdog_ba_handle; - /* firmware access */ struct mutex fw_mutex; struct task_struct *fw_mutex_owner; @@ -225,8 +191,7 @@ struct mwl8k_priv { int pending_tx_pkts; struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; - struct mwl8k_tx_queue txq[MWL8K_MAX_TX_QUEUES]; - u32 txq_offset[MWL8K_MAX_TX_QUEUES]; + struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; bool radio_on; bool radio_short_preamble; @@ -259,7 +224,7 @@ struct mwl8k_priv { * preserve the queue configurations so they can be restored if/when * the firmware image is swapped. */ - struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_WMM_QUEUES]; + struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_QUEUES]; /* async firmware loading state */ unsigned fw_state; @@ -297,17 +262,9 @@ struct mwl8k_vif { #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) #define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8)) -struct tx_traffic_info { - u32 start_time; - u32 pkts; -}; - -#define MWL8K_MAX_TID 8 struct mwl8k_sta { /* Index into station database. Returned by UPDATE_STADB. */ u8 peer_id; - u8 is_ampdu_allowed; - struct tx_traffic_info tx_stats[MWL8K_MAX_TID]; }; #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) @@ -395,12 +352,10 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 -#define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205 #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ #define MWL8K_CMD_UPDATE_STADB 0x1123 -#define MWL8K_CMD_BASTREAM 0x1125 static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) { @@ -440,8 +395,6 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(SET_NEW_STN); MWL8K_CMDNAME(UPDATE_ENCRYPTION); MWL8K_CMDNAME(UPDATE_STADB); - MWL8K_CMDNAME(BASTREAM); - MWL8K_CMDNAME(GET_WATCHDOG_BITMAP); default: snprintf(buf, bufsize, "0x%x", cmd); } @@ -716,7 +669,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) "helper image\n", pci_name(priv->pdev)); return rc; } - msleep(20); + msleep(5); rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); } else { @@ -838,8 +791,8 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb) /* * Make sure the packet header is in the DMA header format (4-address * without QoS), the necessary crypto padding between the header and the - * payload has already been provided by mac80211, but it doesn't add - * tail padding when HW crypto is enabled. + * payload has already been provided by mac80211, but it doesn't add tail + * padding when HW crypto is enabled. * * We have the following trailer padding requirements: * - WEP: 4 trailer bytes (ICV) @@ -1174,9 +1127,6 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) struct mwl8k_rx_queue *rxq = priv->rxq + index; int i; - if (rxq->rxd == NULL) - return; - for (i = 0; i < MWL8K_RX_DESCS; i++) { if (rxq->buf[i].skb != NULL) { pci_unmap_single(priv->pdev, @@ -1369,7 +1319,7 @@ struct mwl8k_tx_desc { __le16 pkt_len; __u8 dest_MAC_addr[ETH_ALEN]; __le32 next_txd_phys_addr; - __le32 timestamp; + __le32 reserved; __le16 rate_info; __u8 peer_id; __u8 tx_frag_cnt; @@ -1433,7 +1383,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) struct mwl8k_priv *priv = hw->priv; int i; - for (i = 0; i < mwl8k_tx_queues(priv); i++) { + for (i = 0; i < MWL8K_TX_QUEUES; i++) { struct mwl8k_tx_queue *txq = priv->txq + i; int fw_owned = 0; int drv_owned = 0; @@ -1502,8 +1452,9 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) if (timeout) { WARN_ON(priv->pending_tx_pkts); - if (retry) + if (retry) { wiphy_notice(hw->wiphy, "tx rings drained\n"); + } break; } @@ -1533,41 +1484,6 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) MWL8K_TXD_STATUS_OK_RETRY | \ MWL8K_TXD_STATUS_OK_MORE_RETRY)) -static int mwl8k_tid_queue_mapping(u8 tid) -{ - BUG_ON(tid > 7); - - switch (tid) { - case 0: - case 3: - return IEEE80211_AC_BE; - break; - case 1: - case 2: - return IEEE80211_AC_BK; - break; - case 4: - case 5: - return IEEE80211_AC_VI; - break; - case 6: - case 7: - return IEEE80211_AC_VO; - break; - default: - return -1; - break; - } -} - -/* The firmware will fill in the rate information - * for each packet that gets queued in the hardware - * and these macros will interpret that info. - */ - -#define RI_FORMAT(a) (a & 0x0001) -#define RI_RATE_ID_MCS(a) ((a & 0x01f8) >> 3) - static int mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) { @@ -1584,10 +1500,6 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) struct sk_buff *skb; struct ieee80211_tx_info *info; u32 status; - struct ieee80211_sta *sta; - struct mwl8k_sta *sta_info = NULL; - u16 rate_info; - struct ieee80211_hdr *wh; tx = txq->head; tx_desc = txq->txd + tx; @@ -1616,40 +1528,18 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) mwl8k_remove_dma_header(skb, tx_desc->qos_control); - wh = (struct ieee80211_hdr *) skb->data; - /* Mark descriptor as unused */ tx_desc->pkt_phys_addr = 0; tx_desc->pkt_len = 0; info = IEEE80211_SKB_CB(skb); - if (ieee80211_is_data(wh->frame_control)) { - sta = info->control.sta; - if (sta) { - sta_info = MWL8K_STA(sta); - BUG_ON(sta_info == NULL); - rate_info = le16_to_cpu(tx_desc->rate_info); - /* If rate is < 6.5 Mpbs for an ht station - * do not form an ampdu. If the station is a - * legacy station (format = 0), do not form an - * ampdu - */ - if (RI_RATE_ID_MCS(rate_info) < 1 || - RI_FORMAT(rate_info) == 0) { - sta_info->is_ampdu_allowed = false; - } else { - sta_info->is_ampdu_allowed = true; - } - } - } - ieee80211_tx_info_clear_status(info); /* Rate control is happening in the firmware. * Ensure no tx rate is being reported. */ - info->status.rates[0].idx = -1; - info->status.rates[0].count = 1; + info->status.rates[0].idx = -1; + info->status.rates[0].count = 1; if (MWL8K_TXD_SUCCESS(status)) info->flags |= IEEE80211_TX_STAT_ACK; @@ -1659,6 +1549,9 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) processed++; } + if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) + ieee80211_wake_queue(hw, index); + return processed; } @@ -1668,9 +1561,6 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) struct mwl8k_priv *priv = hw->priv; struct mwl8k_tx_queue *txq = priv->txq + index; - if (txq->txd == NULL) - return; - mwl8k_txq_reclaim(hw, index, INT_MAX, 1); kfree(txq->skb); @@ -1682,116 +1572,12 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) txq->txd = NULL; } -/* caller must hold priv->stream_lock when calling the stream functions */ -static struct mwl8k_ampdu_stream * -mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) -{ - struct mwl8k_ampdu_stream *stream; - struct mwl8k_priv *priv = hw->priv; - int i; - - for (i = 0; i < priv->num_ampdu_queues; i++) { - stream = &priv->ampdu[i]; - if (stream->state == AMPDU_NO_STREAM) { - stream->sta = sta; - stream->state = AMPDU_STREAM_NEW; - stream->tid = tid; - stream->idx = i; - stream->txq_idx = MWL8K_TX_WMM_QUEUES + i; - wiphy_debug(hw->wiphy, "Added a new stream for %pM %d", - sta->addr, tid); - return stream; - } - } - return NULL; -} - -static int -mwl8k_start_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) -{ - int ret; - - /* if the stream has already been started, don't start it again */ - if (stream->state != AMPDU_STREAM_NEW) - return 0; - ret = ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0); - if (ret) - wiphy_debug(hw->wiphy, "Failed to start stream for %pM %d: " - "%d\n", stream->sta->addr, stream->tid, ret); - else - wiphy_debug(hw->wiphy, "Started stream for %pM %d\n", - stream->sta->addr, stream->tid); - return ret; -} - -static void -mwl8k_remove_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) -{ - wiphy_debug(hw->wiphy, "Remove stream for %pM %d\n", stream->sta->addr, - stream->tid); - memset(stream, 0, sizeof(*stream)); -} - -static struct mwl8k_ampdu_stream * -mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid) -{ - struct mwl8k_priv *priv = hw->priv; - int i; - - for (i = 0 ; i < priv->num_ampdu_queues; i++) { - struct mwl8k_ampdu_stream *stream; - stream = &priv->ampdu[i]; - if (stream->state == AMPDU_NO_STREAM) - continue; - if (!memcmp(stream->sta->addr, addr, ETH_ALEN) && - stream->tid == tid) - return stream; - } - return NULL; -} - -#define MWL8K_AMPDU_PACKET_THRESHOLD 64 -static inline bool mwl8k_ampdu_allowed(struct ieee80211_sta *sta, u8 tid) -{ - struct mwl8k_sta *sta_info = MWL8K_STA(sta); - struct tx_traffic_info *tx_stats; - - BUG_ON(tid >= MWL8K_MAX_TID); - tx_stats = &sta_info->tx_stats[tid]; - - return sta_info->is_ampdu_allowed && - tx_stats->pkts > MWL8K_AMPDU_PACKET_THRESHOLD; -} - -static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid) -{ - struct mwl8k_sta *sta_info = MWL8K_STA(sta); - struct tx_traffic_info *tx_stats; - - BUG_ON(tid >= MWL8K_MAX_TID); - tx_stats = &sta_info->tx_stats[tid]; - - if (tx_stats->start_time == 0) - tx_stats->start_time = jiffies; - - /* reset the packet count after each second elapses. If the number of - * packets ever exceeds the ampdu_min_traffic threshold, we will allow - * an ampdu stream to be started. - */ - if (jiffies - tx_stats->start_time > HZ) { - tx_stats->pkts = 0; - tx_stats->start_time = 0; - } else - tx_stats->pkts++; -} - static void mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) { struct mwl8k_priv *priv = hw->priv; struct ieee80211_tx_info *tx_info; struct mwl8k_vif *mwl8k_vif; - struct ieee80211_sta *sta; struct ieee80211_hdr *wh; struct mwl8k_tx_queue *txq; struct mwl8k_tx_desc *tx; @@ -1799,12 +1585,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) u32 txstatus; u8 txdatarate; u16 qos; - int txpriority; - u8 tid = 0; - struct mwl8k_ampdu_stream *stream = NULL; - bool start_ba_session = false; - bool mgmtframe = false; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; wh = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_data_qos(wh->frame_control)) @@ -1812,9 +1592,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) else qos = 0; - if (ieee80211_is_mgmt(wh->frame_control)) - mgmtframe = true; - if (priv->ap_fw) mwl8k_encapsulate_tx_frame(skb); else @@ -1823,7 +1600,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) wh = &((struct mwl8k_dma_data *)skb->data)->wh; tx_info = IEEE80211_SKB_CB(skb); - sta = tx_info->control.sta; mwl8k_vif = MWL8K_VIF(tx_info->control.vif); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { @@ -1851,91 +1627,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) qos |= MWL8K_QOS_ACK_POLICY_NORMAL; } - /* Queue ADDBA request in the respective data queue. While setting up - * the ampdu stream, mac80211 queues further packets for that - * particular ra/tid pair. However, packets piled up in the hardware - * for that ra/tid pair will still go out. ADDBA request and the - * related data packets going out from different queues asynchronously - * will cause a shift in the receiver window which might result in - * ampdu packets getting dropped at the receiver after the stream has - * been setup. - */ - if (unlikely(ieee80211_is_action(wh->frame_control) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ && - priv->ap_fw)) { - u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - index = mwl8k_tid_queue_mapping(tid); - } - - txpriority = index; - - if (ieee80211_is_data_qos(wh->frame_control) && - skb->protocol != cpu_to_be16(ETH_P_PAE) && - sta->ht_cap.ht_supported && priv->ap_fw) { - tid = qos & 0xf; - mwl8k_tx_count_packet(sta, tid); - spin_lock(&priv->stream_lock); - stream = mwl8k_lookup_stream(hw, sta->addr, tid); - if (stream != NULL) { - if (stream->state == AMPDU_STREAM_ACTIVE) { - txpriority = stream->txq_idx; - index = stream->txq_idx; - } else if (stream->state == AMPDU_STREAM_NEW) { - /* We get here if the driver sends us packets - * after we've initiated a stream, but before - * our ampdu_action routine has been called - * with IEEE80211_AMPDU_TX_START to get the SSN - * for the ADDBA request. So this packet can - * go out with no risk of sequence number - * mismatch. No special handling is required. - */ - } else { - /* Drop packets that would go out after the - * ADDBA request was sent but before the ADDBA - * response is received. If we don't do this, - * the recipient would probably receive it - * after the ADDBA request with SSN 0. This - * will cause the recipient's BA receive window - * to shift, which would cause the subsequent - * packets in the BA stream to be discarded. - * mac80211 queues our packets for us in this - * case, so this is really just a safety check. - */ - wiphy_warn(hw->wiphy, - "Cannot send packet while ADDBA " - "dialog is underway.\n"); - spin_unlock(&priv->stream_lock); - dev_kfree_skb(skb); - return; - } - } else { - /* Defer calling mwl8k_start_stream so that the current - * skb can go out before the ADDBA request. This - * prevents sequence number mismatch at the recepient - * as described above. - */ - if (mwl8k_ampdu_allowed(sta, tid)) { - stream = mwl8k_add_stream(hw, sta, tid); - if (stream != NULL) - start_ba_session = true; - } - } - spin_unlock(&priv->stream_lock); - } - dma = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(priv->pdev, dma)) { wiphy_debug(hw->wiphy, "failed to dma map skb, dropping TX frame.\n"); - if (start_ba_session) { - spin_lock(&priv->stream_lock); - mwl8k_remove_stream(hw, stream); - spin_unlock(&priv->stream_lock); - } dev_kfree_skb(skb); return; } @@ -1944,34 +1641,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txq = priv->txq + index; - /* Mgmt frames that go out frequently are probe - * responses. Other mgmt frames got out relatively - * infrequently. Hence reserve 2 buffers so that - * other mgmt frames do not get dropped due to an - * already queued probe response in one of the - * reserved buffers. - */ - - if (txq->len >= MWL8K_TX_DESCS - 2) { - if (mgmtframe == false || - txq->len == MWL8K_TX_DESCS) { - if (start_ba_session) { - spin_lock(&priv->stream_lock); - mwl8k_remove_stream(hw, stream); - spin_unlock(&priv->stream_lock); - } - spin_unlock_bh(&priv->tx_lock); - dev_kfree_skb(skb); - return; - } - } - BUG_ON(txq->skb[txq->tail] != NULL); txq->skb[txq->tail] = skb; tx = txq->txd + txq->tail; tx->data_rate = txdatarate; - tx->tx_priority = txpriority; + tx->tx_priority = index; tx->qos_control = cpu_to_le16(qos); tx->pkt_phys_addr = cpu_to_le32(dma); tx->pkt_len = cpu_to_le16(skb->len); @@ -1980,11 +1655,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; else tx->peer_id = 0; - - if (priv->ap_fw) - tx->timestamp = cpu_to_le32(ioread32(priv->regs + - MWL8K_HW_TIMER_REGISTER)); - wmb(); tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); @@ -1995,17 +1665,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) if (txq->tail == MWL8K_TX_DESCS) txq->tail = 0; + if (txq->head == txq->tail) + ieee80211_stop_queue(hw, index); + mwl8k_tx_start(priv); spin_unlock_bh(&priv->tx_lock); - - /* Initiate the ampdu session here */ - if (start_ba_session) { - spin_lock(&priv->stream_lock); - if (mwl8k_start_stream(hw, stream)) - mwl8k_remove_stream(hw, stream); - spin_unlock(&priv->stream_lock); - } } @@ -2203,7 +1868,7 @@ struct mwl8k_cmd_get_hw_spec_sta { __u8 mcs_bitmap[16]; __le32 rx_queue_ptr; __le32 num_tx_queues; - __le32 tx_queue_ptrs[MWL8K_TX_WMM_QUEUES]; + __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; __le32 caps2; __le32 num_tx_desc_per_queue; __le32 total_rxd; @@ -2309,8 +1974,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); - cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv)); - for (i = 0; i < mwl8k_tx_queues(priv); i++) + cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); + for (i = 0; i < MWL8K_TX_QUEUES; i++) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); @@ -2352,16 +2017,13 @@ struct mwl8k_cmd_get_hw_spec_ap { __le32 wcbbase2; __le32 wcbbase3; __le32 fw_api_version; - __le32 caps; - __le32 num_of_ampdu_queues; - __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES]; } __packed; static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_get_hw_spec_ap *cmd; - int rc, i; + int rc; u32 api_version; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2393,31 +2055,27 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; - mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); + mwl8k_setup_2ghz_band(hw); priv->ap_macids_supported = 0x000000ff; priv->sta_macids_supported = 0x00000000; - priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues); - if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) { - wiphy_warn(hw->wiphy, "fw reported %d ampdu queues" - " but we only support %d.\n", - priv->num_ampdu_queues, - MWL8K_MAX_AMPDU_QUEUES); - priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES; - } + + off = le32_to_cpu(cmd->wcbbase0) & 0xffff; + iowrite32(priv->txq[0].txd_dma, priv->sram + off); + off = le32_to_cpu(cmd->rxwrptr) & 0xffff; iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); off = le32_to_cpu(cmd->rxrdptr) & 0xffff; iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); - priv->txq_offset[0] = le32_to_cpu(cmd->wcbbase0) & 0xffff; - priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; - priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; - priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; + off = le32_to_cpu(cmd->wcbbase1) & 0xffff; + iowrite32(priv->txq[1].txd_dma, priv->sram + off); + + off = le32_to_cpu(cmd->wcbbase2) & 0xffff; + iowrite32(priv->txq[2].txd_dma, priv->sram + off); - for (i = 0; i < priv->num_ampdu_queues; i++) - priv->txq_offset[i + MWL8K_TX_WMM_QUEUES] = - le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff; + off = le32_to_cpu(cmd->wcbbase3) & 0xffff; + iowrite32(priv->txq[3].txd_dma, priv->sram + off); } done: @@ -2440,20 +2098,12 @@ struct mwl8k_cmd_set_hw_spec { __le32 caps; __le32 rx_queue_ptr; __le32 num_tx_queues; - __le32 tx_queue_ptrs[MWL8K_MAX_TX_QUEUES]; + __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; __le32 flags; __le32 num_tx_desc_per_queue; __le32 total_rxd; } __packed; -/* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause - * packets to expire 500 ms after the timestamp in the tx descriptor. That is, - * the packets that are queued for more than 500ms, will be dropped in the - * hardware. This helps minimizing the issues caused due to head-of-line - * blocking where a slow client can hog the bandwidth and affect traffic to a - * faster client. - */ -#define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 @@ -2474,7 +2124,7 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); - cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv)); + cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); /* * Mac80211 stack has Q0 as highest priority and Q3 as lowest in @@ -2482,15 +2132,14 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) * in that order. Map Q3 of mac80211 to Q0 of firmware so that the * priority is interpreted the right way in firmware. */ - for (i = 0; i < mwl8k_tx_queues(priv); i++) { - int j = mwl8k_tx_queues(priv) - 1 - i; + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + int j = MWL8K_TX_QUEUES - 1 - i; cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma); } cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | - MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | - MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); + MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); @@ -2707,7 +2356,7 @@ struct mwl8k_cmd_tx_power { __le16 bw; __le16 sub_ch; __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; -} __packed; +} __attribute__((packed)); static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw, struct ieee80211_conf *conf, @@ -3473,65 +3122,6 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) return rc; } -/* - * CMD_GET_WATCHDOG_BITMAP. - */ -struct mwl8k_cmd_get_watchdog_bitmap { - struct mwl8k_cmd_pkt header; - u8 bitmap; -} __packed; - -static int mwl8k_cmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) -{ - struct mwl8k_cmd_get_watchdog_bitmap *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_WATCHDOG_BITMAP); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - rc = mwl8k_post_cmd(hw, &cmd->header); - if (!rc) - *bitmap = cmd->bitmap; - - kfree(cmd); - - return rc; -} - -#define INVALID_BA 0xAA -static void mwl8k_watchdog_ba_events(struct work_struct *work) -{ - int rc; - u8 bitmap = 0, stream_index; - struct mwl8k_ampdu_stream *streams; - struct mwl8k_priv *priv = - container_of(work, struct mwl8k_priv, watchdog_ba_handle); - - rc = mwl8k_cmd_get_watchdog_bitmap(priv->hw, &bitmap); - if (rc) - return; - - if (bitmap == INVALID_BA) - return; - - /* the bitmap is the hw queue number. Map it to the ampdu queue. */ - stream_index = bitmap - MWL8K_TX_WMM_QUEUES; - - BUG_ON(stream_index >= priv->num_ampdu_queues); - - streams = &priv->ampdu[stream_index]; - - if (streams->state == AMPDU_STREAM_ACTIVE) - ieee80211_stop_tx_ba_session(streams->sta, streams->tid); - - return; -} - - /* * CMD_BSS_START. */ @@ -3560,152 +3150,6 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, return rc; } -/* - * CMD_BASTREAM. - */ - -/* - * UPSTREAM is tx direction - */ -#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00 -#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01 - -enum ba_stream_action_type { - MWL8K_BA_CREATE, - MWL8K_BA_UPDATE, - MWL8K_BA_DESTROY, - MWL8K_BA_FLUSH, - MWL8K_BA_CHECK, -}; - - -struct mwl8k_create_ba_stream { - __le32 flags; - __le32 idle_thrs; - __le32 bar_thrs; - __le32 window_size; - u8 peer_mac_addr[6]; - u8 dialog_token; - u8 tid; - u8 queue_id; - u8 param_info; - __le32 ba_context; - u8 reset_seq_no_flag; - __le16 curr_seq_no; - u8 sta_src_mac_addr[6]; -} __packed; - -struct mwl8k_destroy_ba_stream { - __le32 flags; - __le32 ba_context; -} __packed; - -struct mwl8k_cmd_bastream { - struct mwl8k_cmd_pkt header; - __le32 action; - union { - struct mwl8k_create_ba_stream create_params; - struct mwl8k_destroy_ba_stream destroy_params; - }; -} __packed; - -static int -mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) -{ - struct mwl8k_cmd_bastream *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->action = cpu_to_le32(MWL8K_BA_CHECK); - - cmd->create_params.queue_id = stream->idx; - memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr, - ETH_ALEN); - cmd->create_params.tid = stream->tid; - - cmd->create_params.flags = - cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) | - cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM); - - rc = mwl8k_post_cmd(hw, &cmd->header); - - kfree(cmd); - - return rc; -} - -static int -mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream, - u8 buf_size) -{ - struct mwl8k_cmd_bastream *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - - cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->action = cpu_to_le32(MWL8K_BA_CREATE); - - cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size); - cmd->create_params.window_size = cpu_to_le32((u32)buf_size); - cmd->create_params.queue_id = stream->idx; - - memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN); - cmd->create_params.tid = stream->tid; - cmd->create_params.curr_seq_no = cpu_to_le16(0); - cmd->create_params.reset_seq_no_flag = 1; - - cmd->create_params.param_info = - (stream->sta->ht_cap.ampdu_factor & - IEEE80211_HT_AMPDU_PARM_FACTOR) | - ((stream->sta->ht_cap.ampdu_density << 2) & - IEEE80211_HT_AMPDU_PARM_DENSITY); - - cmd->create_params.flags = - cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE | - BASTREAM_FLAG_DIRECTION_UPSTREAM); - - rc = mwl8k_post_cmd(hw, &cmd->header); - - wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n", - stream->sta->addr, stream->tid); - kfree(cmd); - - return rc; -} - -static void mwl8k_destroy_ba(struct ieee80211_hw *hw, - struct mwl8k_ampdu_stream *stream) -{ - struct mwl8k_cmd_bastream *cmd; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le32(MWL8K_BA_DESTROY); - - cmd->destroy_params.ba_context = cpu_to_le32(stream->idx); - mwl8k_post_cmd(hw, &cmd->header); - - wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx); - - kfree(cmd); -} - /* * CMD_SET_NEW_STN. */ @@ -3830,7 +3274,7 @@ struct mwl8k_cmd_update_encryption { __u8 mac_addr[6]; __u8 encr_type; -} __packed; +} __attribute__((packed)); struct mwl8k_cmd_set_key { struct mwl8k_cmd_pkt header; @@ -3850,7 +3294,7 @@ struct mwl8k_cmd_set_key { __le16 tkip_tsc_low; __le32 tkip_tsc_high; __u8 mac_addr[6]; -} __packed; +} __attribute__((packed)); enum { MWL8K_ENCR_ENABLE, @@ -4227,11 +3671,6 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) tasklet_schedule(&priv->poll_rx_task); } - if (status & MWL8K_A2H_INT_BA_WATCHDOG) { - status &= ~MWL8K_A2H_INT_BA_WATCHDOG; - ieee80211_queue_work(hw, &priv->watchdog_ba_handle); - } - if (status) iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); @@ -4260,7 +3699,7 @@ static void mwl8k_tx_poll(unsigned long data) spin_lock_bh(&priv->tx_lock); - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) limit -= mwl8k_txq_reclaim(hw, i, limit, 0); if (!priv->pending_tx_pkts && priv->tx_wait != NULL) { @@ -4335,8 +3774,6 @@ static int mwl8k_start(struct ieee80211_hw *hw) /* Enable interrupts */ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - iowrite32(MWL8K_A2H_EVENTS, - priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); rc = mwl8k_fw_lock(hw); if (!rc) { @@ -4392,7 +3829,6 @@ static void mwl8k_stop(struct ieee80211_hw *hw) /* Stop finalize join worker */ cancel_work_sync(&priv->finalize_join_worker); - cancel_work_sync(&priv->watchdog_ba_handle); if (priv->beacon_skb != NULL) dev_kfree_skb(priv->beacon_skb); @@ -4401,7 +3837,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) tasklet_disable(&priv->poll_rx_task); /* Return all skbs to mac80211 */ - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, INT_MAX, 1); } @@ -4522,12 +3958,9 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) conf->power_level = 18; if (priv->ap_fw) { - - if (conf->flags & IEEE80211_CONF_CHANGE_POWER) { - rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); - if (rc) - goto out; - } + rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); + if (rc) + goto out; rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3); if (rc) @@ -4554,7 +3987,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { struct mwl8k_priv *priv = hw->priv; - u32 ap_legacy_rates = 0; + u32 ap_legacy_rates; u8 ap_mcs_rates[16]; int rc; @@ -4879,8 +4312,6 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw, ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); if (ret >= 0) { MWL8K_STA(sta)->peer_id = ret; - if (sta->ht_cap.ht_supported) - MWL8K_STA(sta)->is_ampdu_allowed = true; ret = 0; } @@ -4904,14 +4335,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, rc = mwl8k_fw_lock(hw); if (!rc) { - BUG_ON(queue > MWL8K_TX_WMM_QUEUES - 1); + BUG_ON(queue > MWL8K_TX_QUEUES - 1); memcpy(&priv->wmm_params[queue], params, sizeof(*params)); if (!priv->wmm_enabled) rc = mwl8k_cmd_set_wmm_mode(hw, 1); if (!rc) { - int q = MWL8K_TX_WMM_QUEUES - 1 - queue; + int q = MWL8K_TX_QUEUES - 1 - queue; rc = mwl8k_cmd_set_edca_params(hw, q, params->cw_min, params->cw_max, @@ -4947,118 +4378,21 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, return 0; } -#define MAX_AMPDU_ATTEMPTS 5 - static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) { - - int i, rc = 0; - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_ampdu_stream *stream; - u8 *addr = sta->addr; - - if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) - return -ENOTSUPP; - - spin_lock(&priv->stream_lock); - stream = mwl8k_lookup_stream(hw, addr, tid); - switch (action) { case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_STOP: - break; - case IEEE80211_AMPDU_TX_START: - /* By the time we get here the hw queues may contain outgoing - * packets for this RA/TID that are not part of this BA - * session. The hw will assign sequence numbers to these - * packets as they go out. So if we query the hw for its next - * sequence number and use that for the SSN here, it may end up - * being wrong, which will lead to sequence number mismatch at - * the recipient. To avoid this, we reset the sequence number - * to O for the first MPDU in this BA stream. - */ - *ssn = 0; - if (stream == NULL) { - /* This means that somebody outside this driver called - * ieee80211_start_tx_ba_session. This is unexpected - * because we do our own rate control. Just warn and - * move on. - */ - wiphy_warn(hw->wiphy, "Unexpected call to %s. " - "Proceeding anyway.\n", __func__); - stream = mwl8k_add_stream(hw, sta, tid); - } - if (stream == NULL) { - wiphy_debug(hw->wiphy, "no free AMPDU streams\n"); - rc = -EBUSY; - break; - } - stream->state = AMPDU_STREAM_IN_PROGRESS; - - /* Release the lock before we do the time consuming stuff */ - spin_unlock(&priv->stream_lock); - for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) { - rc = mwl8k_check_ba(hw, stream); - - if (!rc) - break; - /* - * HW queues take time to be flushed, give them - * sufficient time - */ - - msleep(1000); - } - spin_lock(&priv->stream_lock); - if (rc) { - wiphy_err(hw->wiphy, "Stream for tid %d busy after %d" - " attempts\n", tid, MAX_AMPDU_ATTEMPTS); - mwl8k_remove_stream(hw, stream); - rc = -EBUSY; - break; - } - ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); - break; - case IEEE80211_AMPDU_TX_STOP: - if (stream == NULL) - break; - if (stream->state == AMPDU_STREAM_ACTIVE) { - spin_unlock(&priv->stream_lock); - mwl8k_destroy_ba(hw, stream); - spin_lock(&priv->stream_lock); - } - mwl8k_remove_stream(hw, stream); - ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - BUG_ON(stream == NULL); - BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS); - spin_unlock(&priv->stream_lock); - rc = mwl8k_create_ba(hw, stream, buf_size); - spin_lock(&priv->stream_lock); - if (!rc) - stream->state = AMPDU_STREAM_ACTIVE; - else { - spin_unlock(&priv->stream_lock); - mwl8k_destroy_ba(hw, stream); - spin_lock(&priv->stream_lock); - wiphy_debug(hw->wiphy, - "Failed adding stream for sta %pM tid %d\n", - addr, tid); - mwl8k_remove_stream(hw, stream); - } - break; - + if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) + return -ENOTSUPP; + return 0; default: - rc = -ENOTSUPP; + return -ENOTSUPP; } - - spin_unlock(&priv->stream_lock); - return rc; } static const struct ieee80211_ops mwl8k_ops = { @@ -5107,7 +4441,7 @@ enum { MWL8366, }; -#define MWL8K_8366_AP_FW_API 2 +#define MWL8K_8366_AP_FW_API 1 #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) @@ -5273,23 +4607,6 @@ static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image, return rc; } -static int mwl8k_init_txqs(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - int rc = 0; - int i; - - for (i = 0; i < mwl8k_tx_queues(priv); i++) { - rc = mwl8k_txq_init(hw, i); - if (rc) - break; - if (priv->ap_fw) - iowrite32(priv->txq[i].txd_dma, - priv->sram + priv->txq_offset[i]); - } - return rc; -} - /* initialize hw after successfully loading a firmware image */ static int mwl8k_probe_hw(struct ieee80211_hw *hw) { @@ -5317,26 +4634,17 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) goto err_stop_firmware; rxq_refill(hw, 0, INT_MAX); - /* For the sta firmware, we need to know the dma addresses of tx queues - * before sending MWL8K_CMD_GET_HW_SPEC. So we must initialize them - * prior to issuing this command. But for the AP case, we learn the - * total number of queues from the result CMD_GET_HW_SPEC, so for this - * case we must initialize the tx queues after. - */ - priv->num_ampdu_queues = 0; - if (!priv->ap_fw) { - rc = mwl8k_init_txqs(hw); + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + rc = mwl8k_txq_init(hw, i); if (rc) goto err_free_queues; } iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY| - MWL8K_A2H_INT_BA_WATCHDOG, + iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); - iowrite32(MWL8K_A2H_INT_OPC_DONE, - priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); + iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); @@ -5345,8 +4653,6 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) goto err_free_queues; } - memset(priv->ampdu, 0, sizeof(priv->ampdu)); - /* * Temporarily enable interrupts. Initial firmware host * commands use interrupts and avoid polling. Disable @@ -5357,8 +4663,6 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) /* Get config data, mac addrs etc */ if (priv->ap_fw) { rc = mwl8k_cmd_get_hw_spec_ap(hw); - if (!rc) - rc = mwl8k_init_txqs(hw); if (!rc) rc = mwl8k_cmd_set_hw_spec(hw); } else { @@ -5401,7 +4705,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) free_irq(priv->pdev->irq, hw); err_free_queues: - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); @@ -5423,7 +4727,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) mwl8k_stop(hw); mwl8k_rxq_deinit(hw, 0); - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); rc = mwl8k_init_firmware(hw, fw_image, false); @@ -5442,7 +4746,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) if (rc) goto fail; - for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) { + for (i = 0; i < MWL8K_TX_QUEUES; i++) { rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); if (rc) goto fail; @@ -5476,7 +4780,7 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) hw->channel_change_time = 10; - hw->queues = MWL8K_TX_WMM_QUEUES; + hw->queues = MWL8K_TX_QUEUES; /* Set rssi values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; @@ -5492,8 +4796,6 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); - /* Handle watchdog ba events */ - INIT_WORK(&priv->watchdog_ba_handle, mwl8k_watchdog_ba_events); /* TX reclaim and RX tasklets. */ tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); @@ -5513,8 +4815,6 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->stream_lock); - priv->tx_wait = NULL; rc = mwl8k_probe_hw(hw); @@ -5536,7 +4836,7 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) return 0; err_unprobe_hw: - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); @@ -5695,10 +4995,10 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) mwl8k_hw_reset(priv); /* Return all skbs to mac80211 */ - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, INT_MAX, 1); - for (i = 0; i < mwl8k_tx_queues(priv); i++) + for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); diff --git a/trunk/drivers/net/wireless/p54/eeprom.c b/trunk/drivers/net/wireless/p54/eeprom.c index 54cc0bba66b9..13d750da9301 100644 --- a/trunk/drivers/net/wireless/p54/eeprom.c +++ b/trunk/drivers/net/wireless/p54/eeprom.c @@ -491,7 +491,7 @@ static int p54_parse_rssical(struct ieee80211_hw *dev, struct pda_rssi_cal_entry *cal = (void *) &data[offset]; for (i = 0; i < entries; i++) { - u16 freq = 0; + u16 freq; switch (i) { case IEEE80211_BAND_2GHZ: freq = 2437; diff --git a/trunk/drivers/net/wireless/p54/fwio.c b/trunk/drivers/net/wireless/p54/fwio.c index b6a061cbbdec..2fab7d20ffc2 100644 --- a/trunk/drivers/net/wireless/p54/fwio.c +++ b/trunk/drivers/net/wireless/p54/fwio.c @@ -727,34 +727,3 @@ int p54_fetch_statistics(struct p54_common *priv) p54_tx(priv, skb); return 0; } - -int p54_set_groupfilter(struct p54_common *priv) -{ - struct p54_group_address_table *grp; - struct sk_buff *skb; - bool on = false; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*grp), - P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE, GFP_KERNEL); - if (!skb) - return -ENOMEM; - - grp = (struct p54_group_address_table *)skb_put(skb, sizeof(*grp)); - - on = !(priv->filter_flags & FIF_ALLMULTI) && - (priv->mc_maclist_num > 0 && - priv->mc_maclist_num <= MC_FILTER_ADDRESS_NUM); - - if (on) { - grp->filter_enable = cpu_to_le16(1); - grp->num_address = cpu_to_le16(priv->mc_maclist_num); - memcpy(grp->mac_list, priv->mc_maclist, sizeof(grp->mac_list)); - } else { - grp->filter_enable = cpu_to_le16(0); - grp->num_address = cpu_to_le16(0); - memset(grp->mac_list, 0, sizeof(grp->mac_list)); - } - - p54_tx(priv, skb); - return 0; -} diff --git a/trunk/drivers/net/wireless/p54/lmac.h b/trunk/drivers/net/wireless/p54/lmac.h index 3d8d622bec55..eb581abc1079 100644 --- a/trunk/drivers/net/wireless/p54/lmac.h +++ b/trunk/drivers/net/wireless/p54/lmac.h @@ -540,7 +540,6 @@ int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set); int p54_setup_mac(struct p54_common *priv); int p54_set_ps(struct p54_common *priv); int p54_fetch_statistics(struct p54_common *priv); -int p54_set_groupfilter(struct p54_common *priv); /* e/v DCF setup */ int p54_set_edcf(struct p54_common *priv); diff --git a/trunk/drivers/net/wireless/p54/main.c b/trunk/drivers/net/wireless/p54/main.c index c5c1254ec093..356e6bb443a6 100644 --- a/trunk/drivers/net/wireless/p54/main.c +++ b/trunk/drivers/net/wireless/p54/main.c @@ -308,31 +308,6 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) return ret; } -static u64 p54_prepare_multicast(struct ieee80211_hw *dev, - struct netdev_hw_addr_list *mc_list) -{ - struct p54_common *priv = dev->priv; - struct netdev_hw_addr *ha; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) != - ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list)); - /* - * The first entry is reserved for the global broadcast MAC. - * Otherwise the firmware will drop it and ARP will no longer work. - */ - i = 1; - priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i; - netdev_hw_addr_list_for_each(ha, mc_list) { - memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN); - i++; - if (i >= ARRAY_SIZE(priv->mc_maclist)) - break; - } - - return 1; /* update */ -} - static void p54_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, @@ -341,16 +316,12 @@ static void p54_configure_filter(struct ieee80211_hw *dev, struct p54_common *priv = dev->priv; *total_flags &= FIF_PROMISC_IN_BSS | - FIF_ALLMULTI | FIF_OTHER_BSS; priv->filter_flags = *total_flags; if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) p54_setup_mac(priv); - - if (changed_flags & FIF_ALLMULTI || multicast) - p54_set_groupfilter(priv); } static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, @@ -620,7 +591,6 @@ static const struct ieee80211_ops p54_ops = { .config = p54_config, .flush = p54_flush, .bss_info_changed = p54_bss_info_changed, - .prepare_multicast = p54_prepare_multicast, .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, .get_stats = p54_get_stats, @@ -690,7 +660,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) init_completion(&priv->beacon_comp); INIT_DELAYED_WORK(&priv->work, p54_work); - memset(&priv->mc_maclist[0], ~0, ETH_ALEN); return dev; } EXPORT_SYMBOL_GPL(p54_init_common); diff --git a/trunk/drivers/net/wireless/p54/p54.h b/trunk/drivers/net/wireless/p54/p54.h index 799d05e12595..50730fc23fe5 100644 --- a/trunk/drivers/net/wireless/p54/p54.h +++ b/trunk/drivers/net/wireless/p54/p54.h @@ -211,10 +211,8 @@ struct p54_common { /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; - u8 mc_maclist[4][ETH_ALEN]; u16 wakeup_timer; unsigned int filter_flags; - int mc_maclist_num; int mode; u32 tsf_low32, tsf_high32; u32 basic_rate_mask; diff --git a/trunk/drivers/net/wireless/rt2x00/Kconfig b/trunk/drivers/net/wireless/rt2x00/Kconfig index c45773108283..f630552427b7 100644 --- a/trunk/drivers/net/wireless/rt2x00/Kconfig +++ b/trunk/drivers/net/wireless/rt2x00/Kconfig @@ -59,6 +59,7 @@ config RT2800PCI select RT2800_LIB select RT2X00_LIB_PCI if PCI select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X + select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE select RT2X00_LIB_CRYPTO select CRC_CCITT @@ -73,13 +74,17 @@ config RT2800PCI if RT2800PCI config RT2800PCI_RT33XX - bool "rt2800pci - Include support for rt33xx devices" - default y + bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- This adds support for rt33xx wireless chipset family to the rt2800pci driver. Supported chips: RT3390 + Support for these devices is non-functional at the moment and is + intended for testers and developers. + config RT2800PCI_RT35XX bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -95,12 +100,15 @@ config RT2800PCI_RT35XX config RT2800PCI_RT53XX bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL - default y + default n ---help--- This adds support for rt53xx wireless chipset family to the rt2800pci driver. Supported chips: RT5390 + Support for these devices is non-functional at the moment and is + intended for testers and developers. + endif config RT2500USB @@ -132,6 +140,7 @@ config RT2800USB depends on USB select RT2800_LIB select RT2X00_LIB_USB + select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE select RT2X00_LIB_CRYPTO select CRC_CCITT @@ -144,13 +153,17 @@ config RT2800USB if RT2800USB config RT2800USB_RT33XX - bool "rt2800usb - Include support for rt33xx devices" - default y + bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- This adds support for rt33xx wireless chipset family to the rt2800usb driver. Supported chips: RT3370 + Support for these devices is non-functional at the moment and is + intended for testers and developers. + config RT2800USB_RT35XX bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -194,6 +207,9 @@ config RT2X00_LIB_USB config RT2X00_LIB tristate +config RT2X00_LIB_HT + boolean + config RT2X00_LIB_FIRMWARE boolean select FW_LOADER diff --git a/trunk/drivers/net/wireless/rt2x00/Makefile b/trunk/drivers/net/wireless/rt2x00/Makefile index 349d5b8284a4..971339858297 100644 --- a/trunk/drivers/net/wireless/rt2x00/Makefile +++ b/trunk/drivers/net/wireless/rt2x00/Makefile @@ -7,6 +7,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o +rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c index 937f9e8bf05f..329f3283697b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, } } -static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; @@ -1368,10 +1368,8 @@ static void rt2400pci_tbtt_tasklet(unsigned long data) static void rt2400pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - if (rt2x00pci_rxdone(rt2x00dev)) - tasklet_schedule(&rt2x00dev->rxdone_tasklet); - else - rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); + rt2x00pci_rxdone(rt2x00dev); + rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); } static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) @@ -1536,13 +1534,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Check if the BBP tuning should be enabled. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); return 0; } @@ -1640,9 +1638,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires the atim queue and DMA-mapped skbs. */ - __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1720,9 +1718,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, - .set_antenna = rt2x00mac_set_antenna, - .get_antenna = rt2x00mac_get_antenna, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { @@ -1743,7 +1738,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .start_queue = rt2400pci_start_queue, .kick_queue = rt2400pci_kick_queue, .stop_queue = rt2400pci_stop_queue, - .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt2400pci_write_tx_desc, .write_beacon = rt2400pci_write_beacon, .fill_rxdone = rt2400pci_fill_rxdone, @@ -1805,11 +1799,10 @@ static const struct rt2x00_ops rt2400pci_ops = { * RT2400pci module information. */ static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = { - { PCI_DEVICE(0x1814, 0x0101) }, + { PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) }, { 0, } }; - MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver."); @@ -1817,16 +1810,10 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards"); MODULE_DEVICE_TABLE(pci, rt2400pci_device_table); MODULE_LICENSE("GPL"); -static int rt2400pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) -{ - return rt2x00pci_probe(pci_dev, &rt2400pci_ops); -} - static struct pci_driver rt2400pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2400pci_device_table, - .probe = rt2400pci_probe, + .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c index d27d7b8ba3b6..58277878889e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, } } -static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; @@ -1500,10 +1500,8 @@ static void rt2500pci_tbtt_tasklet(unsigned long data) static void rt2500pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - if (rt2x00pci_rxdone(rt2x00dev)) - tasklet_schedule(&rt2x00dev->rxdone_tasklet); - else - rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); + rt2x00pci_rxdone(rt2x00dev); + rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); } static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) @@ -1687,14 +1685,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Check if the BBP tuning should be enabled. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); /* * Read the RSSI <-> dBm offset information. @@ -1958,9 +1956,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires the atim queue and DMA-mapped skbs. */ - __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2013,9 +2011,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, - .set_antenna = rt2x00mac_set_antenna, - .get_antenna = rt2x00mac_get_antenna, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { @@ -2036,7 +2031,6 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .start_queue = rt2500pci_start_queue, .kick_queue = rt2500pci_kick_queue, .stop_queue = rt2500pci_stop_queue, - .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt2500pci_write_tx_desc, .write_beacon = rt2500pci_write_beacon, .fill_rxdone = rt2500pci_fill_rxdone, @@ -2098,7 +2092,7 @@ static const struct rt2x00_ops rt2500pci_ops = { * RT2500pci module information. */ static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = { - { PCI_DEVICE(0x1814, 0x0201) }, + { PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) }, { 0, } }; @@ -2109,16 +2103,10 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards"); MODULE_DEVICE_TABLE(pci, rt2500pci_device_table); MODULE_LICENSE("GPL"); -static int rt2500pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) -{ - return rt2x00pci_probe(pci_dev, &rt2500pci_ops); -} - static struct pci_driver rt2500pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2500pci_device_table, - .probe = rt2500pci_probe, + .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c index b21f81231a09..979fe6596a2d 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Read the RSSI <-> dBm offset information. @@ -1790,13 +1790,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires the atim queue */ - __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); if (!modparam_nohwcrypt) { - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); } - __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1823,9 +1824,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, - .set_antenna = rt2x00mac_set_antenna, - .get_antenna = rt2x00mac_get_antenna, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1907,54 +1905,58 @@ static const struct rt2x00_ops rt2500usb_ops = { */ static struct usb_device_id rt2500usb_device_table[] = { /* ASUS */ - { USB_DEVICE(0x0b05, 0x1706) }, - { USB_DEVICE(0x0b05, 0x1707) }, + { USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x7050) }, - { USB_DEVICE(0x050d, 0x7051) }, + { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Cisco Systems */ - { USB_DEVICE(0x13b1, 0x000d) }, - { USB_DEVICE(0x13b1, 0x0011) }, - { USB_DEVICE(0x13b1, 0x001a) }, + { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* CNet */ + { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c02) }, + { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, /* D-LINK */ - { USB_DEVICE(0x2001, 0x3c00) }, + { USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x8001) }, - { USB_DEVICE(0x1044, 0x8007) }, + { USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Hercules */ - { USB_DEVICE(0x06f8, 0xe000) }, + { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Melco */ - { USB_DEVICE(0x0411, 0x005e) }, - { USB_DEVICE(0x0411, 0x0066) }, - { USB_DEVICE(0x0411, 0x0067) }, - { USB_DEVICE(0x0411, 0x008b) }, - { USB_DEVICE(0x0411, 0x0097) }, + { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x6861) }, - { USB_DEVICE(0x0db0, 0x6865) }, - { USB_DEVICE(0x0db0, 0x6869) }, + { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x1706) }, - { USB_DEVICE(0x148f, 0x2570) }, - { USB_DEVICE(0x148f, 0x9020) }, + { USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Sagem */ - { USB_DEVICE(0x079b, 0x004b) }, + { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Siemens */ - { USB_DEVICE(0x0681, 0x3c06) }, + { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, /* SMC */ - { USB_DEVICE(0x0707, 0xee13) }, + { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Spairon */ - { USB_DEVICE(0x114b, 0x0110) }, + { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, /* SURECOM */ - { USB_DEVICE(0x0769, 0x11f3) }, + { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Trust */ - { USB_DEVICE(0x0eb0, 0x9020) }, + { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, /* VTech */ - { USB_DEVICE(0x0f88, 0x3012) }, + { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0260) }, + { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, { 0, } }; @@ -1965,16 +1967,10 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards"); MODULE_DEVICE_TABLE(usb, rt2500usb_device_table); MODULE_LICENSE("GPL"); -static int rt2500usb_probe(struct usb_interface *usb_intf, - const struct usb_device_id *id) -{ - return rt2x00usb_probe(usb_intf, &rt2500usb_ops); -} - static struct usb_driver rt2500usb_driver = { .name = KBUILD_MODNAME, .id_table = rt2500usb_device_table, - .probe = rt2500usb_probe, + .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800.h b/trunk/drivers/net/wireless/rt2x00/rt2800.h index 3b3d851fe266..70b9abbdeb9e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800.h @@ -2103,59 +2103,6 @@ struct mac_iveiv_entry { #define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) -/* - * EEPROM temperature compensation boundaries 802.11BG - * MINUS4: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -4) - * MINUS3: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -3) - */ -#define EEPROM_TSSI_BOUND_BG1 0x0037 -#define EEPROM_TSSI_BOUND_BG1_MINUS4 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_BG1_MINUS3 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11BG - * MINUS2: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -2) - * MINUS1: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -1) - */ -#define EEPROM_TSSI_BOUND_BG2 0x0038 -#define EEPROM_TSSI_BOUND_BG2_MINUS2 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_BG2_MINUS1 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11BG - * REF: Reference TSSI value, no tx power changes needed - * PLUS1: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 1) - */ -#define EEPROM_TSSI_BOUND_BG3 0x0039 -#define EEPROM_TSSI_BOUND_BG3_REF FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_BG3_PLUS1 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11BG - * PLUS2: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 2) - * PLUS3: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 3) - */ -#define EEPROM_TSSI_BOUND_BG4 0x003a -#define EEPROM_TSSI_BOUND_BG4_PLUS2 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_BG4_PLUS3 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11BG - * PLUS4: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 4) - * AGC_STEP: Temperature compensation step. - */ -#define EEPROM_TSSI_BOUND_BG5 0x003b -#define EEPROM_TSSI_BOUND_BG5_PLUS4 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00) - /* * EEPROM TXPOWER 802.11A */ @@ -2165,59 +2112,6 @@ struct mac_iveiv_entry { #define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) -/* - * EEPROM temperature compensation boundaries 802.11A - * MINUS4: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -4) - * MINUS3: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -3) - */ -#define EEPROM_TSSI_BOUND_A1 0x006a -#define EEPROM_TSSI_BOUND_A1_MINUS4 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_A1_MINUS3 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11A - * MINUS2: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -2) - * MINUS1: If the actual TSSI is below this boundary, tx power needs to be - * reduced by (agc_step * -1) - */ -#define EEPROM_TSSI_BOUND_A2 0x006b -#define EEPROM_TSSI_BOUND_A2_MINUS2 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_A2_MINUS1 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11A - * REF: Reference TSSI value, no tx power changes needed - * PLUS1: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 1) - */ -#define EEPROM_TSSI_BOUND_A3 0x006c -#define EEPROM_TSSI_BOUND_A3_REF FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_A3_PLUS1 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11A - * PLUS2: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 2) - * PLUS3: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 3) - */ -#define EEPROM_TSSI_BOUND_A4 0x006d -#define EEPROM_TSSI_BOUND_A4_PLUS2 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_A4_PLUS3 FIELD16(0xff00) - -/* - * EEPROM temperature compensation boundaries 802.11A - * PLUS4: If the actual TSSI is above this boundary, tx power needs to be - * increased by (agc_step * 4) - * AGC_STEP: Temperature compensation step. - */ -#define EEPROM_TSSI_BOUND_A5 0x006e -#define EEPROM_TSSI_BOUND_A5_PLUS4 FIELD16(0x00ff) -#define EEPROM_TSSI_BOUND_A5_AGC_STEP FIELD16(0xff00) - /* * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index d79c8fd41138..2ee6cebb9b25 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -687,9 +687,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status) mcs = real_mcs; } - if (aggr == 1 || ampdu == 1) - __set_bit(TXDONE_AMPDU, &txdesc.flags); - /* * Ralink has a retry mechanism using a global fallback * table. We setup this fallback table to try the immediate @@ -730,20 +727,34 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; struct queue_entry *entry; u32 reg; - u8 qid; + u8 pid; + int i; - while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { + /* + * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO + * at most X times and also stop processing once the TX_STA_FIFO_VALID + * flag is not set anymore. + * + * The legacy drivers use X=TX_RING_SIZE but state in a comment + * that the TX_STA_FIFO stack has a size of 16. We stick to our + * tx ring size for now. + */ + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { + rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); + if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) + break; - /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus - * qid is guaranteed to be one of the TX QIDs + /* + * Skip this entry when it contains an invalid + * queue identication number. */ - qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); - queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); - if (unlikely(!queue)) { - WARNING(rt2x00dev, "Got TX status for an unavailable " - "queue %u, dropping\n", qid); + pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); + if (pid >= QID_RX) + continue; + + queue = rt2x00queue_get_tx_queue(rt2x00dev, pid); + if (unlikely(!queue)) continue; - } /* * Inside each queue, we process each entry in a chronological @@ -935,49 +946,25 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev, unsigned int ledmode = rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, EEPROM_FREQ_LED_MODE); - u32 reg; - - /* Check for SoC (SOC devices don't support MCU requests) */ - if (rt2x00_is_soc(led->rt2x00dev)) { - rt2800_register_read(led->rt2x00dev, LED_CFG, ®); - - /* Set LED Polarity */ - rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); - - /* Set LED Mode */ - if (led->type == LED_TYPE_RADIO) { - rt2x00_set_field32(®, LED_CFG_G_LED_MODE, - enabled ? 3 : 0); - } else if (led->type == LED_TYPE_ASSOC) { - rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, - enabled ? 3 : 0); - } else if (led->type == LED_TYPE_QUALITY) { - rt2x00_set_field32(®, LED_CFG_R_LED_MODE, - enabled ? 3 : 0); - } - rt2800_register_write(led->rt2x00dev, LED_CFG, reg); - - } else { - if (led->type == LED_TYPE_RADIO) { - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? 0x20 : 0); - } else if (led->type == LED_TYPE_ASSOC) { - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); - } else if (led->type == LED_TYPE_QUALITY) { - /* - * The brightness is divided into 6 levels (0 - 5), - * The specs tell us the following levels: - * 0, 1 ,3, 7, 15, 31 - * to determine the level in a simple way we can simply - * work with bitshifting: - * (1 << level) - 1 - */ - rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, - (1 << brightness / (LED_FULL / 6)) - 1, - polarity); - } + if (led->type == LED_TYPE_RADIO) { + rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? 0x20 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * The specs tell us the following levels: + * 0, 1 ,3, 7, 15, 31 + * to determine the level in a simple way we can simply + * work with bitshifting: + * (1 << level) - 1 + */ + rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + (1 << brightness / (LED_FULL / 6)) - 1, + polarity); } } @@ -1231,25 +1218,6 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - if (conf->sync == TSF_SYNC_AP_NONE) { - /* - * Tune beacon queue transmit parameters for AP mode - */ - rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); - rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0); - rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1); - rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); - rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0); - rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); - } else { - rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); - rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4); - rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2); - rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); - rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16); - rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); - } } if (flags & CONFIG_UPDATE_MAC) { @@ -1768,8 +1736,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, if (rf->channel <= 14) { if (!rt2x00_rt(rt2x00dev, RT5390)) { - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, - &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, + &rt2x00dev->flags)) { rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 75, 0x46); } else { @@ -1780,7 +1748,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } else { rt2800_bbp_write(rt2x00dev, 82, 0xf2); - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) rt2800_bbp_write(rt2x00dev, 75, 0x46); else rt2800_bbp_write(rt2x00dev, 75, 0x50); @@ -1845,131 +1813,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); } -static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) -{ - u8 tssi_bounds[9]; - u8 current_tssi; - u16 eeprom; - u8 step; - int i; - - /* - * Read TSSI boundaries for temperature compensation from - * the EEPROM. - * - * Array idx 0 1 2 3 4 5 6 7 8 - * Matching Delta value -4 -3 -2 -1 0 +1 +2 +3 +4 - * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 - */ - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); - tssi_bounds[0] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG1_MINUS4); - tssi_bounds[1] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG1_MINUS3); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); - tssi_bounds[2] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG2_MINUS2); - tssi_bounds[3] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG2_MINUS1); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); - tssi_bounds[4] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG3_REF); - tssi_bounds[5] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG3_PLUS1); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); - tssi_bounds[6] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG4_PLUS2); - tssi_bounds[7] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG4_PLUS3); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); - tssi_bounds[8] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG5_PLUS4); - - step = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_BG5_AGC_STEP); - } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); - tssi_bounds[0] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A1_MINUS4); - tssi_bounds[1] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A1_MINUS3); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); - tssi_bounds[2] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A2_MINUS2); - tssi_bounds[3] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A2_MINUS1); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); - tssi_bounds[4] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A3_REF); - tssi_bounds[5] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A3_PLUS1); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); - tssi_bounds[6] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A4_PLUS2); - tssi_bounds[7] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A4_PLUS3); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); - tssi_bounds[8] = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A5_PLUS4); - - step = rt2x00_get_field16(eeprom, - EEPROM_TSSI_BOUND_A5_AGC_STEP); - } - - /* - * Check if temperature compensation is supported. - */ - if (tssi_bounds[4] == 0xff) - return 0; - - /* - * Read current TSSI (BBP 49). - */ - rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi); - - /* - * Compare TSSI value (BBP49) with the compensation boundaries - * from the EEPROM and increase or decrease tx power. - */ - for (i = 0; i <= 3; i++) { - if (current_tssi > tssi_bounds[i]) - break; - } - - if (i == 4) { - for (i = 8; i >= 5; i--) { - if (current_tssi < tssi_bounds[i]) - break; - } - } - - return (i - 4) * step; -} - static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, enum ieee80211_band band) { u16 eeprom; u8 comp_en; u8 comp_type; - int comp_value = 0; + int comp_value; rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); - /* - * HT40 compensation not required. - */ - if (eeprom == 0xffff || - !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + if (eeprom == 0xffff) return 0; if (band == IEEE80211_BAND_2GHZ) { @@ -1999,9 +1853,11 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, return comp_value; } -static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, - enum ieee80211_band band, int power_level, - u8 txpower, int delta) +static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, + int is_rate_b, + enum ieee80211_band band, + int power_level, + u8 txpower) { u32 reg; u16 eeprom; @@ -2009,11 +1865,15 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, u8 eirp_txpower; u8 eirp_txpower_criterion; u8 reg_limit; + int bw_comp = 0; if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) return txpower; - if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band); + + if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) { /* * Check if eirp txpower exceed txpower_limit. * We use OFDM 6M as criterion and its eirp txpower @@ -2035,19 +1895,18 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, EEPROM_EIRP_MAX_TX_POWER_5GHZ); eirp_txpower = eirp_txpower_criterion + (txpower - criterion) + - (is_rate_b ? 4 : 0) + delta; + (is_rate_b ? 4 : 0) + bw_comp; reg_limit = (eirp_txpower > power_level) ? (eirp_txpower - power_level) : 0; } else reg_limit = 0; - return txpower + delta - reg_limit; + return txpower + bw_comp - reg_limit; } static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, - enum ieee80211_band band, - int power_level) + struct ieee80211_conf *conf) { u8 txpower; u16 eeprom; @@ -2055,17 +1914,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, u32 reg; u8 r1; u32 offset; - int delta; - - /* - * Calculate HT40 compensation delta - */ - delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); - - /* - * calculate temperature compensation delta - */ - delta += rt2800_get_gain_calibration_delta(rt2x00dev); + enum ieee80211_band band = conf->channel->band; + int power_level = conf->power_level; /* * set to normal bbp tx power control mode: +/- 0dBm @@ -2094,8 +1944,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower); /* @@ -2105,8 +1955,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower); /* @@ -2116,8 +1966,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower); /* @@ -2127,8 +1977,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); /* read the next four txpower values */ @@ -2143,8 +1993,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower); /* @@ -2154,8 +2004,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower); /* @@ -2165,8 +2015,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower); /* @@ -2176,8 +2026,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, */ txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); - txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, - power_level, txpower, delta); + txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, + power_level, txpower); rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower); rt2800_register_write(rt2x00dev, offset, reg); @@ -2187,13 +2037,6 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, } } -void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) -{ - rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band, - rt2x00dev->tx_power); -} -EXPORT_SYMBOL_GPL(rt2800_gain_calibration); - static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf) { @@ -2247,12 +2090,10 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev, if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { rt2800_config_channel(rt2x00dev, libconf->conf, &libconf->rf, &libconf->channel); - rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, - libconf->conf->power_level); + rt2800_config_txpower(rt2x00dev, libconf->conf); } if (flags & IEEE80211_CONF_CHANGE_POWER) - rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, - libconf->conf->power_level); + rt2800_config_txpower(rt2x00dev, libconf->conf); if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) rt2800_config_retry_limit(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_PS) @@ -2413,7 +2254,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) } else if (rt2800_is_305x_soc(rt2x00dev)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); - rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); } else if (rt2x00_rt(rt2x00dev, RT5390)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -3314,8 +3155,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { - if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, - &rt2x00dev->cap_flags)) + if (!test_bit(CONFIG_EXTERNAL_LNA_BG, + &rt2x00dev->flags)) rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); } rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); @@ -3738,15 +3579,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) - __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); + __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) - __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); + __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); /* * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) - __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Store led settings, for correct led behaviour. @@ -3766,7 +3607,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) < EIRP_MAX_TX_POWER_LIMIT) - __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags); return 0; } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h index f2d15941c71a..0c92d86a36f4 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h @@ -181,7 +181,6 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); -void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index 08d3947fcb26..808073aa9dcc 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) return; for (i = 0; i < 200; i++) { - rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); + rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || @@ -80,8 +80,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) if (i == 200) ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) @@ -105,7 +105,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg; - rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); + rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); @@ -127,7 +127,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, !!eeprom->reg_chip_select); - rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); + rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); } static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) @@ -135,7 +135,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) struct eeprom_93cx6 eeprom; u32 reg; - rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); + rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2800pci_eepromregister_read; @@ -195,9 +195,9 @@ static void rt2800pci_start_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: /* @@ -207,15 +207,15 @@ static void rt2800pci_start_queue(struct data_queue *queue) tasklet_enable(&rt2x00dev->tbtt_tasklet); tasklet_enable(&rt2x00dev->pretbtt_tasklet); - rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); + rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); - rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); + rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); break; default: break; @@ -233,13 +233,11 @@ static void rt2800pci_kick_queue(struct data_queue *queue) case QID_AC_BE: case QID_AC_BK: entry = rt2x00queue_get_entry(queue, Q_INDEX); - rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), - entry->entry_idx); + rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx); break; case QID_MGMT: entry = rt2x00queue_get_entry(queue, Q_INDEX); - rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5), - entry->entry_idx); + rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx); break; default: break; @@ -253,20 +251,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); - rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: - rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); + rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); - rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); + rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); /* * Wait for tbtt tasklets to finish. @@ -297,7 +295,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); - rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); /* * Write firmware to device. @@ -305,11 +303,11 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); - rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); - rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); - rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; } @@ -353,7 +351,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) * Set RX IDX in register to inform hardware that we have * handled this entry and it is available for reuse again. */ - rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, + rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); } else { rt2x00_desc_read(entry_priv->desc, 1, &word); @@ -371,51 +369,45 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) * Initialize registers. */ entry_priv = rt2x00dev->tx[0].entries[0].priv_data; - rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, - rt2x00dev->tx[0].limit); - rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); - rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0); + rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); + rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); + rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0); + rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0); entry_priv = rt2x00dev->tx[1].entries[0].priv_data; - rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, - rt2x00dev->tx[1].limit); - rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); - rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0); + rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); + rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); + rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0); + rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0); entry_priv = rt2x00dev->tx[2].entries[0].priv_data; - rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, - rt2x00dev->tx[2].limit); - rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); - rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0); + rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); + rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); + rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0); + rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0); entry_priv = rt2x00dev->tx[3].entries[0].priv_data; - rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, - rt2x00dev->tx[3].limit); - rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); - rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); + rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); + rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); + rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0); + rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0); entry_priv = rt2x00dev->rx->entries[0].priv_data; - rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, - rt2x00dev->rx[0].limit); - rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, - rt2x00dev->rx[0].limit - 1); - rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); + rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); + rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); + rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); + rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0); /* * Enable global DMA configuration */ - rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); + rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0); return 0; } @@ -435,8 +427,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, * should clear the register to assure a clean state. */ if (state == STATE_RADIO_IRQ_ON) { - rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); + rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); /* * Enable tasklets. The beacon related tasklets are @@ -448,7 +440,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, } spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); - rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); @@ -467,7 +459,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0); rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); - rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); if (state == STATE_RADIO_IRQ_OFF) { @@ -488,7 +480,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) /* * Reset DMA indexes */ - rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); @@ -496,26 +488,26 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); - rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); - rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); if (rt2x00_rt(rt2x00dev, RT5390)) { - rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®); + rt2800_register_read(rt2x00dev, AUX_CTRL, ®); rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); - rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg); + rt2800_register_write(rt2x00dev, AUX_CTRL, reg); } - rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); return 0; } @@ -533,8 +525,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) { if (rt2x00_is_soc(rt2x00dev)) { rt2800_disable_radio(rt2x00dev); - rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0); + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); } } @@ -545,10 +537,8 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02); rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); } else if (state == STATE_SLEEP) { - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, - 0xffffffff); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, - 0xffffffff); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff); rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01); } @@ -727,13 +717,12 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } -static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) +static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; struct queue_entry *entry; u32 status; u8 qid; - int max_tx_done = 16; while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); @@ -770,16 +759,11 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); rt2800_txdone_entry(entry, status); - - if (--max_tx_done == 0) - break; } - - return !max_tx_done; } -static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; @@ -788,17 +772,15 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, * access needs locking. */ spin_lock_irq(&rt2x00dev->irqmask_lock); - rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, irq_field, 1); - rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irq(&rt2x00dev->irqmask_lock); } static void rt2800pci_txstatus_tasklet(unsigned long data) { - struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - if (rt2800pci_txdone(rt2x00dev)) - tasklet_schedule(&rt2x00dev->txstatus_tasklet); + rt2800pci_txdone((struct rt2x00_dev *)data); /* * No need to enable the tx status interrupt here as we always @@ -824,10 +806,8 @@ static void rt2800pci_tbtt_tasklet(unsigned long data) static void rt2800pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - if (rt2x00pci_rxdone(rt2x00dev)) - tasklet_schedule(&rt2x00dev->rxdone_tasklet); - else - rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); + rt2x00pci_rxdone(rt2x00dev); + rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); } static void rt2800pci_autowake_tasklet(unsigned long data) @@ -861,7 +841,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) * need to lock the kfifo. */ for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { - rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status); + rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) break; @@ -883,8 +863,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) u32 reg, mask; /* Read status and ACK all interrupts */ - rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); + rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; @@ -924,9 +904,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) * the tasklet will reenable the appropriate interrupts. */ spin_lock(&rt2x00dev->irqmask_lock); - rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); reg &= mask; - rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock(&rt2x00dev->irqmask_lock); return IRQ_HANDLED; @@ -976,28 +956,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. */ - __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); /* * This device has a pre tbtt interrupt and thus fetches * a new beacon directly prior to transmission. */ - __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags); /* * This device requires firmware. */ if (!rt2x00_is_soc(rt2x00dev)) - __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags); if (!modparam_nohwcrypt) - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1028,7 +1008,6 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .ampdu_action = rt2800_ampdu_action, .flush = rt2x00mac_flush, .get_survey = rt2800_get_survey, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2800_ops rt2800pci_rt2800_ops = { @@ -1064,11 +1043,9 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, - .gain_calibration = rt2800_gain_calibration, .start_queue = rt2800pci_start_queue, .kick_queue = rt2800pci_kick_queue, .stop_queue = rt2800pci_stop_queue, - .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt2800pci_write_tx_desc, .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, @@ -1128,36 +1105,36 @@ static const struct rt2x00_ops rt2800pci_ops = { */ #ifdef CONFIG_PCI static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { - { PCI_DEVICE(0x1814, 0x0601) }, - { PCI_DEVICE(0x1814, 0x0681) }, - { PCI_DEVICE(0x1814, 0x0701) }, - { PCI_DEVICE(0x1814, 0x0781) }, - { PCI_DEVICE(0x1814, 0x3090) }, - { PCI_DEVICE(0x1814, 0x3091) }, - { PCI_DEVICE(0x1814, 0x3092) }, - { PCI_DEVICE(0x1432, 0x7708) }, - { PCI_DEVICE(0x1432, 0x7727) }, - { PCI_DEVICE(0x1432, 0x7728) }, - { PCI_DEVICE(0x1432, 0x7738) }, - { PCI_DEVICE(0x1432, 0x7748) }, - { PCI_DEVICE(0x1432, 0x7758) }, - { PCI_DEVICE(0x1432, 0x7768) }, - { PCI_DEVICE(0x1462, 0x891a) }, - { PCI_DEVICE(0x1a3b, 0x1059) }, + { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, #ifdef CONFIG_RT2800PCI_RT33XX - { PCI_DEVICE(0x1814, 0x3390) }, + { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif #ifdef CONFIG_RT2800PCI_RT35XX - { PCI_DEVICE(0x1432, 0x7711) }, - { PCI_DEVICE(0x1432, 0x7722) }, - { PCI_DEVICE(0x1814, 0x3060) }, - { PCI_DEVICE(0x1814, 0x3062) }, - { PCI_DEVICE(0x1814, 0x3562) }, - { PCI_DEVICE(0x1814, 0x3592) }, - { PCI_DEVICE(0x1814, 0x3593) }, + { PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif #ifdef CONFIG_RT2800PCI_RT53XX - { PCI_DEVICE(0x1814, 0x5390) }, + { PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif { 0, } }; @@ -1193,16 +1170,10 @@ static struct platform_driver rt2800soc_driver = { #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ #ifdef CONFIG_PCI -static int rt2800pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) -{ - return rt2x00pci_probe(pci_dev, &rt2800pci_ops); -} - static struct pci_driver rt2800pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2800pci_device_table, - .probe = rt2800pci_probe, + .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index 0d4e8fa3e1f8..37509d019910 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); break; default: break; @@ -82,78 +82,22 @@ static void rt2800usb_stop_queue(struct data_queue *queue) switch (queue->qid) { case QID_RX: - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); break; case QID_BEACON: - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); break; default: break; } } -/* - * test if there is an entry in any TX queue for which DMA is done - * but the TX status has not been returned yet - */ -static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - tx_queue_for_each(rt2x00dev, queue) { - if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) != - rt2x00queue_get_entry(queue, Q_INDEX_DONE)) - return true; - } - return false; -} - -static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, - int urb_status, u32 tx_status) -{ - if (urb_status) { - WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status); - return; - } - - /* try to read all TX_STA_FIFO entries before scheduling txdone_work */ - if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) { - if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) { - WARNING(rt2x00dev, "TX status FIFO overrun, " - "drop tx status report.\n"); - queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); - } else - rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, - rt2800usb_tx_sta_fifo_read_completed); - } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { - queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); - } else if (rt2800usb_txstatus_pending(rt2x00dev)) { - mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); - } -} - -static void rt2800usb_tx_dma_done(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - - rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, - rt2800usb_tx_sta_fifo_read_completed); -} - -static void rt2800usb_tx_sta_fifo_timeout(unsigned long data) -{ - struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - - rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, - rt2800usb_tx_sta_fifo_read_completed); -} - /* * Firmware functions */ @@ -185,11 +129,11 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, /* * Write firmware to device. */ - rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, - data + offset, length); + rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + data + offset, length); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); /* * Send firmware request to device to load firmware, @@ -204,7 +148,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, } msleep(10); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; } @@ -222,22 +166,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2800_wait_csr_ready(rt2x00dev)) return -EBUSY; - rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); - rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); - rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); + rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_RESET, REGISTER_TIMEOUT); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); return 0; } @@ -249,7 +193,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev))) return -EIO; - rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); + rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); @@ -262,7 +206,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); - rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); + rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); return rt2800_enable_radio(rt2x00dev); } @@ -338,12 +282,12 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) unsigned int i; u32 reg; - rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { WARNING(rt2x00dev, "TX HW queue 0 timed out," " invoke forced kick\n"); - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012); + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); for (i = 0; i < 10; i++) { udelay(10); @@ -351,15 +295,15 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) break; } - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); } - rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { WARNING(rt2x00dev, "TX HW queue 1 timed out," " invoke forced kick\n"); - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a); + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); for (i = 0; i < 10; i++) { udelay(10); @@ -367,7 +311,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) break; } - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); } rt2x00usb_watchdog(rt2x00dev); @@ -476,24 +420,13 @@ static void rt2800usb_work_txdone(struct work_struct *work) while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - break; - if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) - rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); - else if (rt2x00queue_status_timeout(entry)) - rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); - else + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) break; + + rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); } } - - /* - * The hw may delay sending the packet after DMA complete - * if the medium is busy, thus the TX_STA_FIFO entry is - * also delayed -> use a timer to retrieve it. - */ - if (rt2800usb_txstatus_pending(rt2x00dev)) - mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); } /* @@ -620,23 +553,19 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. */ - __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); /* * This device requires firmware. */ - __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); if (!modparam_nohwcrypt) - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); - - setup_timer(&rt2x00dev->txstatus_timer, - rt2800usb_tx_sta_fifo_timeout, - (unsigned long) rt2x00dev); + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); /* * Set the rssi offset. @@ -673,7 +602,6 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .ampdu_action = rt2800_ampdu_action, .flush = rt2x00mac_flush, .get_survey = rt2800_get_survey, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -702,13 +630,11 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, - .gain_calibration = rt2800_gain_calibration, .watchdog = rt2800usb_watchdog, .start_queue = rt2800usb_start_queue, .kick_queue = rt2x00usb_kick_queue, .stop_queue = rt2800usb_stop_queue, .flush_queue = rt2x00usb_flush_queue, - .tx_dma_done = rt2800usb_tx_dma_done, .write_tx_desc = rt2800usb_write_tx_desc, .write_tx_data = rt2800usb_write_tx_data, .write_beacon = rt2800_write_beacon, @@ -769,332 +695,294 @@ static const struct rt2x00_ops rt2800usb_ops = { */ static struct usb_device_id rt2800usb_device_table[] = { /* Abocom */ - { USB_DEVICE(0x07b8, 0x2870) }, - { USB_DEVICE(0x07b8, 0x2770) }, - { USB_DEVICE(0x07b8, 0x3070) }, - { USB_DEVICE(0x07b8, 0x3071) }, - { USB_DEVICE(0x07b8, 0x3072) }, - { USB_DEVICE(0x1482, 0x3c09) }, + { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AirTies */ - { USB_DEVICE(0x1eda, 0x2012) }, - { USB_DEVICE(0x1eda, 0x2310) }, + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Allwin */ - { USB_DEVICE(0x8516, 0x2070) }, - { USB_DEVICE(0x8516, 0x2770) }, - { USB_DEVICE(0x8516, 0x2870) }, - { USB_DEVICE(0x8516, 0x3070) }, - { USB_DEVICE(0x8516, 0x3071) }, - { USB_DEVICE(0x8516, 0x3072) }, - /* Alpha Networks */ - { USB_DEVICE(0x14b2, 0x3c06) }, - { USB_DEVICE(0x14b2, 0x3c07) }, - { USB_DEVICE(0x14b2, 0x3c09) }, - { USB_DEVICE(0x14b2, 0x3c12) }, - { USB_DEVICE(0x14b2, 0x3c23) }, - { USB_DEVICE(0x14b2, 0x3c25) }, - { USB_DEVICE(0x14b2, 0x3c27) }, - { USB_DEVICE(0x14b2, 0x3c28) }, - { USB_DEVICE(0x14b2, 0x3c2c) }, + { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amit */ - { USB_DEVICE(0x15c5, 0x0008) }, + { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ - { USB_DEVICE(0x1690, 0x0740) }, + { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ASUS */ - { USB_DEVICE(0x0b05, 0x1731) }, - { USB_DEVICE(0x0b05, 0x1732) }, - { USB_DEVICE(0x0b05, 0x1742) }, - { USB_DEVICE(0x0b05, 0x1784) }, - { USB_DEVICE(0x1761, 0x0b05) }, + { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3247) }, - { USB_DEVICE(0x13d3, 0x3273) }, - { USB_DEVICE(0x13d3, 0x3305) }, - { USB_DEVICE(0x13d3, 0x3307) }, - { USB_DEVICE(0x13d3, 0x3321) }, + { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x8053) }, - { USB_DEVICE(0x050d, 0x805c) }, - { USB_DEVICE(0x050d, 0x815c) }, - { USB_DEVICE(0x050d, 0x825b) }, - { USB_DEVICE(0x050d, 0x935a) }, - { USB_DEVICE(0x050d, 0x935b) }, + { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Buffalo */ - { USB_DEVICE(0x0411, 0x00e8) }, - { USB_DEVICE(0x0411, 0x016f) }, - { USB_DEVICE(0x0411, 0x01a2) }, + { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Conceptronic */ + { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Corega */ - { USB_DEVICE(0x07aa, 0x002f) }, - { USB_DEVICE(0x07aa, 0x003c) }, - { USB_DEVICE(0x07aa, 0x003f) }, - { USB_DEVICE(0x18c5, 0x0012) }, + { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c09) }, - { USB_DEVICE(0x07d1, 0x3c0a) }, - { USB_DEVICE(0x07d1, 0x3c0d) }, - { USB_DEVICE(0x07d1, 0x3c0e) }, - { USB_DEVICE(0x07d1, 0x3c0f) }, - { USB_DEVICE(0x07d1, 0x3c11) }, - { USB_DEVICE(0x07d1, 0x3c16) }, + { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Draytek */ - { USB_DEVICE(0x07fa, 0x7712) }, + { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ - { USB_DEVICE(0x7392, 0x7711) }, - { USB_DEVICE(0x7392, 0x7717) }, - { USB_DEVICE(0x7392, 0x7718) }, + { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ - { USB_DEVICE(0x203d, 0x1480) }, - { USB_DEVICE(0x203d, 0x14a9) }, + { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x9701) }, - { USB_DEVICE(0x1740, 0x9702) }, - { USB_DEVICE(0x1740, 0x9703) }, - { USB_DEVICE(0x1740, 0x9705) }, - { USB_DEVICE(0x1740, 0x9706) }, - { USB_DEVICE(0x1740, 0x9707) }, - { USB_DEVICE(0x1740, 0x9708) }, - { USB_DEVICE(0x1740, 0x9709) }, - /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0012) }, + { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800b) }, - { USB_DEVICE(0x1044, 0x800d) }, + { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Hawking */ - { USB_DEVICE(0x0e66, 0x0001) }, - { USB_DEVICE(0x0e66, 0x0003) }, - { USB_DEVICE(0x0e66, 0x0009) }, - { USB_DEVICE(0x0e66, 0x000b) }, - { USB_DEVICE(0x0e66, 0x0013) }, - { USB_DEVICE(0x0e66, 0x0017) }, - { USB_DEVICE(0x0e66, 0x0018) }, + { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0945) }, - { USB_DEVICE(0x04bb, 0x0947) }, - { USB_DEVICE(0x04bb, 0x0948) }, + { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ - { USB_DEVICE(0x13b1, 0x0031) }, - { USB_DEVICE(0x1737, 0x0070) }, - { USB_DEVICE(0x1737, 0x0071) }, + { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Logitec */ - { USB_DEVICE(0x0789, 0x0162) }, - { USB_DEVICE(0x0789, 0x0163) }, - { USB_DEVICE(0x0789, 0x0164) }, - { USB_DEVICE(0x0789, 0x0166) }, + { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ - { USB_DEVICE(0x100d, 0x9031) }, + { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x3820) }, - { USB_DEVICE(0x0db0, 0x3821) }, - { USB_DEVICE(0x0db0, 0x3822) }, - { USB_DEVICE(0x0db0, 0x3870) }, - { USB_DEVICE(0x0db0, 0x3871) }, - { USB_DEVICE(0x0db0, 0x6899) }, - { USB_DEVICE(0x0db0, 0x821a) }, - { USB_DEVICE(0x0db0, 0x822a) }, - { USB_DEVICE(0x0db0, 0x822b) }, - { USB_DEVICE(0x0db0, 0x822c) }, - { USB_DEVICE(0x0db0, 0x870a) }, - { USB_DEVICE(0x0db0, 0x871a) }, - { USB_DEVICE(0x0db0, 0x871b) }, - { USB_DEVICE(0x0db0, 0x871c) }, - { USB_DEVICE(0x0db0, 0x899a) }, + { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Para */ - { USB_DEVICE(0x20b8, 0x8888) }, + { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Pegatron */ - { USB_DEVICE(0x1d4d, 0x000c) }, - { USB_DEVICE(0x1d4d, 0x000e) }, - { USB_DEVICE(0x1d4d, 0x0011) }, + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Philips */ - { USB_DEVICE(0x0471, 0x200f) }, + { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ - { USB_DEVICE(0x2019, 0xab25) }, - { USB_DEVICE(0x2019, 0xed06) }, + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304) }, + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x2070) }, - { USB_DEVICE(0x148f, 0x2770) }, - { USB_DEVICE(0x148f, 0x2870) }, - { USB_DEVICE(0x148f, 0x3070) }, - { USB_DEVICE(0x148f, 0x3071) }, - { USB_DEVICE(0x148f, 0x3072) }, + { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Samsung */ - { USB_DEVICE(0x04e8, 0x2018) }, + { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Siemens */ - { USB_DEVICE(0x129b, 0x1828) }, + { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0017) }, - { USB_DEVICE(0x0df6, 0x002b) }, - { USB_DEVICE(0x0df6, 0x002c) }, - { USB_DEVICE(0x0df6, 0x002d) }, - { USB_DEVICE(0x0df6, 0x0039) }, - { USB_DEVICE(0x0df6, 0x003b) }, - { USB_DEVICE(0x0df6, 0x003d) }, - { USB_DEVICE(0x0df6, 0x003e) }, - { USB_DEVICE(0x0df6, 0x003f) }, - { USB_DEVICE(0x0df6, 0x0040) }, - { USB_DEVICE(0x0df6, 0x0042) }, - { USB_DEVICE(0x0df6, 0x0047) }, - { USB_DEVICE(0x0df6, 0x0048) }, - { USB_DEVICE(0x0df6, 0x0051) }, - { USB_DEVICE(0x0df6, 0x005f) }, + { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ - { USB_DEVICE(0x083a, 0x6618) }, - { USB_DEVICE(0x083a, 0x7511) }, - { USB_DEVICE(0x083a, 0x7512) }, - { USB_DEVICE(0x083a, 0x7522) }, - { USB_DEVICE(0x083a, 0x8522) }, - { USB_DEVICE(0x083a, 0xa618) }, - { USB_DEVICE(0x083a, 0xa701) }, - { USB_DEVICE(0x083a, 0xa702) }, - { USB_DEVICE(0x083a, 0xa703) }, - { USB_DEVICE(0x083a, 0xb522) }, + { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sparklan */ - { USB_DEVICE(0x15a9, 0x0006) }, + { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sweex */ - { USB_DEVICE(0x177f, 0x0302) }, - /* U-Media */ - { USB_DEVICE(0x157e, 0x300e) }, - { USB_DEVICE(0x157e, 0x3013) }, + { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* U-Media*/ + { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ZCOM */ - { USB_DEVICE(0x0cde, 0x0022) }, - { USB_DEVICE(0x0cde, 0x0025) }, + { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0280) }, - { USB_DEVICE(0x5a57, 0x0282) }, - { USB_DEVICE(0x5a57, 0x0283) }, - { USB_DEVICE(0x5a57, 0x5257) }, + { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ - { USB_DEVICE(0x0586, 0x3416) }, - { USB_DEVICE(0x0586, 0x3418) }, - { USB_DEVICE(0x0586, 0x341e) }, - { USB_DEVICE(0x0586, 0x343e) }, + { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, #ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ - { USB_DEVICE(0x148f, 0x3370) }, - { USB_DEVICE(0x148f, 0x8070) }, + { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0050) }, + { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif #ifdef CONFIG_RT2800USB_RT35XX /* Allwin */ - { USB_DEVICE(0x8516, 0x3572) }, + { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ - { USB_DEVICE(0x1690, 0x0744) }, + { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Cisco */ - { USB_DEVICE(0x167b, 0x4001) }, + { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x9801) }, + { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0944) }, - /* Linksys */ - { USB_DEVICE(0x13b1, 0x002f) }, - { USB_DEVICE(0x1737, 0x0079) }, + { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x3572) }, + { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0041) }, + { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Toshiba */ - { USB_DEVICE(0x0930, 0x0a07) }, + { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0284) }, + { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif #ifdef CONFIG_RT2800USB_UNKNOWN /* * Unclear what kind of devices these are (they aren't supported by the * vendor linux driver). */ - /* Abocom */ - { USB_DEVICE(0x07b8, 0x3073) }, - { USB_DEVICE(0x07b8, 0x3074) }, - /* Alpha Networks */ - { USB_DEVICE(0x14b2, 0x3c08) }, - { USB_DEVICE(0x14b2, 0x3c11) }, /* Amigo */ - { USB_DEVICE(0x0e0b, 0x9031) }, - { USB_DEVICE(0x0e0b, 0x9041) }, + { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ASUS */ - { USB_DEVICE(0x0b05, 0x166a) }, - { USB_DEVICE(0x0b05, 0x1760) }, - { USB_DEVICE(0x0b05, 0x1761) }, - { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x179d) }, + { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3262) }, - { USB_DEVICE(0x13d3, 0x3284) }, - { USB_DEVICE(0x13d3, 0x3322) }, + { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x1003) }, - { USB_DEVICE(0x050d, 0x825a) }, + { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Buffalo */ - { USB_DEVICE(0x0411, 0x012e) }, - { USB_DEVICE(0x0411, 0x0148) }, - { USB_DEVICE(0x0411, 0x0150) }, - { USB_DEVICE(0x0411, 0x015d) }, + { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Conceptronic */ + { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Corega */ - { USB_DEVICE(0x07aa, 0x0041) }, - { USB_DEVICE(0x07aa, 0x0042) }, - { USB_DEVICE(0x18c5, 0x0008) }, + { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c0b) }, - { USB_DEVICE(0x07d1, 0x3c13) }, - { USB_DEVICE(0x07d1, 0x3c15) }, - { USB_DEVICE(0x07d1, 0x3c17) }, - { USB_DEVICE(0x2001, 0x3c17) }, + { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ - { USB_DEVICE(0x7392, 0x4085) }, - { USB_DEVICE(0x7392, 0x7722) }, + { USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ - { USB_DEVICE(0x203d, 0x14a1) }, + { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0010) }, + { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800c) }, - /* Huawei */ - { USB_DEVICE(0x148f, 0xf101) }, - /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x094b) }, + { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, /* LevelOne */ - { USB_DEVICE(0x1740, 0x0605) }, - { USB_DEVICE(0x1740, 0x0615) }, + { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ - { USB_DEVICE(0x1737, 0x0077) }, - { USB_DEVICE(0x1737, 0x0078) }, - /* Logitec */ - { USB_DEVICE(0x0789, 0x0168) }, - { USB_DEVICE(0x0789, 0x0169) }, + { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ - { USB_DEVICE(0x100d, 0x9032) }, + { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ovislink */ - { USB_DEVICE(0x1b75, 0x3071) }, - { USB_DEVICE(0x1b75, 0x3072) }, + { USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Pegatron */ - { USB_DEVICE(0x05a6, 0x0101) }, - { USB_DEVICE(0x1d4d, 0x0002) }, - { USB_DEVICE(0x1d4d, 0x0010) }, + { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ - { USB_DEVICE(0x2019, 0x5201) }, - { USB_DEVICE(0x2019, 0xab24) }, + { USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Qcom */ - { USB_DEVICE(0x18e8, 0x6259) }, - /* RadioShack */ - { USB_DEVICE(0x08b9, 0x1197) }, - /* Sitecom */ - { USB_DEVICE(0x0df6, 0x003c) }, - { USB_DEVICE(0x0df6, 0x004a) }, - { USB_DEVICE(0x0df6, 0x004d) }, - { USB_DEVICE(0x0df6, 0x0053) }, - { USB_DEVICE(0x0df6, 0x0060) }, - { USB_DEVICE(0x0df6, 0x0062) }, + { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ - { USB_DEVICE(0x083a, 0xa512) }, - { USB_DEVICE(0x083a, 0xc522) }, - { USB_DEVICE(0x083a, 0xd522) }, - { USB_DEVICE(0x083a, 0xf511) }, + { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sweex */ - { USB_DEVICE(0x177f, 0x0153) }, - { USB_DEVICE(0x177f, 0x0313) }, + { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ - { USB_DEVICE(0x0586, 0x341a) }, + { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif { 0, } }; @@ -1107,16 +995,10 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table); MODULE_FIRMWARE(FIRMWARE_RT2870); MODULE_LICENSE("GPL"); -static int rt2800usb_probe(struct usb_interface *usb_intf, - const struct usb_device_id *id) -{ - return rt2x00usb_probe(usb_intf, &rt2800usb_ops); -} - static struct usb_driver rt2800usb_driver = { .name = KBUILD_MODNAME, .id_table = rt2800usb_device_table, - .probe = rt2800usb_probe, + .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index acf561f7cde3..a3940d7300a4 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -37,7 +37,6 @@ #include #include #include -#include #include @@ -349,11 +348,6 @@ struct link { * to bring the device/driver back into the desired state. */ struct delayed_work watchdog_work; - - /* - * Work structure for scheduling periodic AGC adjustments. - */ - struct delayed_work agc_work; }; enum rt2x00_delayed_flags { @@ -562,7 +556,6 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*link_tuner) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); - void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); /* * Data queue handlers. @@ -571,8 +564,7 @@ struct rt2x00lib_ops { void (*start_queue) (struct data_queue *queue); void (*kick_queue) (struct data_queue *queue); void (*stop_queue) (struct data_queue *queue); - void (*flush_queue) (struct data_queue *queue, bool drop); - void (*tx_dma_done) (struct queue_entry *entry); + void (*flush_queue) (struct data_queue *queue); /* * TX control handlers @@ -645,11 +637,11 @@ struct rt2x00_ops { }; /* - * rt2x00 state flags + * rt2x00 device flags */ -enum rt2x00_state_flags { +enum rt2x00_flags { /* - * Device flags + * Device state flags */ DEVICE_STATE_PRESENT, DEVICE_STATE_REGISTERED_HW, @@ -658,47 +650,43 @@ enum rt2x00_state_flags { DEVICE_STATE_ENABLED_RADIO, DEVICE_STATE_SCANNING, + /* + * Driver requirements + */ + DRIVER_REQUIRE_FIRMWARE, + DRIVER_REQUIRE_BEACON_GUARD, + DRIVER_REQUIRE_ATIM_QUEUE, + DRIVER_REQUIRE_DMA, + DRIVER_REQUIRE_COPY_IV, + DRIVER_REQUIRE_L2PAD, + DRIVER_REQUIRE_TXSTATUS_FIFO, + DRIVER_REQUIRE_TASKLET_CONTEXT, + DRIVER_REQUIRE_SW_SEQNO, + DRIVER_REQUIRE_HT_TX_DESC, + + /* + * Driver features + */ + CONFIG_SUPPORT_HW_BUTTON, + CONFIG_SUPPORT_HW_CRYPTO, + CONFIG_SUPPORT_POWER_LIMIT, + DRIVER_SUPPORT_CONTROL_FILTERS, + DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, + DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, + DRIVER_SUPPORT_LINK_TUNING, + DRIVER_SUPPORT_WATCHDOG, + /* * Driver configuration */ + CONFIG_FRAME_TYPE, + CONFIG_RF_SEQUENCE, + CONFIG_EXTERNAL_LNA_A, + CONFIG_EXTERNAL_LNA_BG, + CONFIG_DOUBLE_ANTENNA, CONFIG_CHANNEL_HT40, }; -/* - * rt2x00 capability flags - */ -enum rt2x00_capability_flags { - /* - * Requirements - */ - REQUIRE_FIRMWARE, - REQUIRE_BEACON_GUARD, - REQUIRE_ATIM_QUEUE, - REQUIRE_DMA, - REQUIRE_COPY_IV, - REQUIRE_L2PAD, - REQUIRE_TXSTATUS_FIFO, - REQUIRE_TASKLET_CONTEXT, - REQUIRE_SW_SEQNO, - REQUIRE_HT_TX_DESC, - - /* - * Capabilities - */ - CAPABILITY_HW_BUTTON, - CAPABILITY_HW_CRYPTO, - CAPABILITY_POWER_LIMIT, - CAPABILITY_CONTROL_FILTERS, - CAPABILITY_CONTROL_FILTER_PSPOLL, - CAPABILITY_PRE_TBTT_INTERRUPT, - CAPABILITY_LINK_TUNING, - CAPABILITY_FRAME_TYPE, - CAPABILITY_RF_SEQUENCE, - CAPABILITY_EXTERNAL_LNA_A, - CAPABILITY_EXTERNAL_LNA_BG, - CAPABILITY_DOUBLE_ANTENNA, -}; - /* * rt2x00 device structure. */ @@ -745,19 +733,12 @@ struct rt2x00_dev { #endif /* CONFIG_RT2X00_LIB_LEDS */ /* - * Device state flags. - * In these flags the current status is stored. - * Access to these flags should occur atomically. + * Device flags. + * In these flags the current status and some + * of the device capabilities are stored. */ unsigned long flags; - /* - * Device capabiltiy flags. - * In these flags the device/driver capabilities are stored. - * Access to these flags should occur non-atomically. - */ - unsigned long cap_flags; - /* * Device information, Bus IRQ and name (PCI, SoC) */ @@ -924,11 +905,6 @@ struct rt2x00_dev { */ DECLARE_KFIFO_PTR(txstatus_fifo, u32); - /* - * Timer to ensure tx status reports are read (rt2800usb). - */ - struct timer_list txstatus_timer; - /* * Tasklet for processing tx status reports (rt2800pci). */ @@ -1254,10 +1230,6 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); -int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); -int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); -void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, - u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); /* * Driver allocation handlers. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00config.c b/trunk/drivers/net/wireless/rt2x00/rt2x00config.c index 2a313b6d378d..e7f67d5eda52 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00config.c @@ -109,6 +109,15 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); } +static inline +enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant, + enum antenna default_ant) +{ + if (current_ant != ANTENNA_SW_DIVERSITY) + return current_ant; + return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B; +} + void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, struct antenna_setup config) { @@ -117,35 +126,19 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, struct antenna_setup *active = &rt2x00dev->link.ant.active; /* - * When the caller tries to send the SW diversity, - * we must update the ANTENNA_RX_DIVERSITY flag to - * enable the antenna diversity in the link tuner. - * - * Secondly, we must guarentee we never send the - * software antenna diversity command to the driver. + * Failsafe: Make sure we are not sending the + * ANTENNA_SW_DIVERSITY state to the driver. + * If that happens, fallback to hardware defaults, + * or our own default. */ - if (!(ant->flags & ANTENNA_RX_DIVERSITY)) { - if (config.rx == ANTENNA_SW_DIVERSITY) { - ant->flags |= ANTENNA_RX_DIVERSITY; - - if (def->rx == ANTENNA_SW_DIVERSITY) - config.rx = ANTENNA_B; - else - config.rx = def->rx; - } - } else if (config.rx == ANTENNA_SW_DIVERSITY) + if (!(ant->flags & ANTENNA_RX_DIVERSITY)) + config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); + else if (config.rx == ANTENNA_SW_DIVERSITY) config.rx = active->rx; - if (!(ant->flags & ANTENNA_TX_DIVERSITY)) { - if (config.tx == ANTENNA_SW_DIVERSITY) { - ant->flags |= ANTENNA_TX_DIVERSITY; - - if (def->tx == ANTENNA_SW_DIVERSITY) - config.tx = ANTENNA_B; - else - config.tx = def->tx; - } - } else if (config.tx == ANTENNA_SW_DIVERSITY) + if (!(ant->flags & ANTENNA_TX_DIVERSITY)) + config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); + else if (config.tx == ANTENNA_SW_DIVERSITY) config.tx = active->tx; /* @@ -170,34 +163,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00queue_start_queue(rt2x00dev->rx); } -static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - int center_channel; - u16 i; - - /* - * Initialize center channel to current channel. - */ - center_channel = spec->channels[conf->channel->hw_value].channel; - - /* - * Adjust center channel to HT40+ and HT40- operation. - */ - if (conf_is_ht40_plus(conf)) - center_channel += 2; - else if (conf_is_ht40_minus(conf)) - center_channel -= (center_channel == 14) ? 1 : 2; - - for (i = 0; i < spec->num_channels; i++) - if (spec->channels[i].channel == center_channel) - return i; - - WARN_ON(1); - return conf->channel->hw_value; -} - void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, unsigned int ieee80211_flags) @@ -211,10 +176,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { if (conf_is_ht40(conf)) { - set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); hw_value = rt2x00ht_center_channel(rt2x00dev, conf); } else { - clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); hw_value = conf->channel->hw_value; } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00crypto.c b/trunk/drivers/net/wireless/rt2x00/rt2x00crypto.c index e1e0c51fcde8..5e9074bf2b8e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) + if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key) return; __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); @@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, struct ieee80211_key_conf *key = tx_info->control.hw_key; unsigned int overhead = 0; - if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key) + if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key) return overhead; /* diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c b/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c index 78787fcc919e..c92db3264741 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -63,8 +63,7 @@ struct rt2x00debug_intf { * - driver folder * - driver file * - chipset file - * - device state flags file - * - device capability flags file + * - device flags file * - register folder * - csr offset/value files * - eeprom offset/value files @@ -79,7 +78,6 @@ struct rt2x00debug_intf { struct dentry *driver_entry; struct dentry *chipset_entry; struct dentry *dev_flags; - struct dentry *cap_flags; struct dentry *register_folder; struct dentry *csr_off_entry; struct dentry *csr_val_entry; @@ -555,35 +553,6 @@ static const struct file_operations rt2x00debug_fop_dev_flags = { .llseek = default_llseek, }; -static ssize_t rt2x00debug_read_cap_flags(struct file *file, - char __user *buf, - size_t length, - loff_t *offset) -{ - struct rt2x00debug_intf *intf = file->private_data; - char line[16]; - size_t size; - - if (*offset) - return 0; - - size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags); - - if (copy_to_user(buf, line, size)) - return -EFAULT; - - *offset += size; - return size; -} - -static const struct file_operations rt2x00debug_fop_cap_flags = { - .owner = THIS_MODULE, - .read = rt2x00debug_read_cap_flags, - .open = rt2x00debug_file_open, - .release = rt2x00debug_file_release, - .llseek = default_llseek, -}; - static struct dentry *rt2x00debug_create_file_driver(const char *name, struct rt2x00debug_intf *intf, @@ -599,6 +568,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, blob->data = data; data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name); data += sprintf(data, "version:\t%s\n", DRV_VERSION); + data += sprintf(data, "compiled:\t%s %s\n", __DATE__, __TIME__); blob->size = strlen(blob->data); return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); @@ -683,12 +653,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) if (IS_ERR(intf->dev_flags) || !intf->dev_flags) goto exit; - intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR, - intf->driver_folder, intf, - &rt2x00debug_fop_cap_flags); - if (IS_ERR(intf->cap_flags) || !intf->cap_flags) - goto exit; - intf->register_folder = debugfs_create_dir("register", intf->driver_folder); if (IS_ERR(intf->register_folder) || !intf->register_folder) @@ -742,7 +706,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) intf, &rt2x00debug_fop_queue_stats); #ifdef CONFIG_RT2X00_LIB_CRYPTO - if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) intf->crypto_stats_entry = debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, intf, &rt2x00debug_fop_crypto_stats); @@ -780,7 +744,6 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) debugfs_remove(intf->csr_off_entry); debugfs_remove(intf->register_folder); debugfs_remove(intf->dev_flags); - debugfs_remove(intf->cap_flags); debugfs_remove(intf->chipset_entry); debugfs_remove(intf->driver_entry); debugfs_remove(intf->driver_folder); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index 7776d9f1f297..84eb6ad36377 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "rt2x00.h" #include "rt2x00lib.h" @@ -71,7 +70,6 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) */ rt2x00queue_start_queues(rt2x00dev); rt2x00link_start_tuner(rt2x00dev); - rt2x00link_start_agc(rt2x00dev); /* * Start watchdog monitoring. @@ -94,7 +92,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Stop all queues */ - rt2x00link_stop_agc(rt2x00dev); rt2x00link_stop_tuner(rt2x00dev); rt2x00queue_stop_queues(rt2x00dev); rt2x00queue_flush_queues(rt2x00dev, true); @@ -200,7 +197,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) * here as they will fetch the next beacon directly prior to * transmission. */ - if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags)) + if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags)) return; /* fetch next beacon */ @@ -225,7 +222,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); void rt2x00lib_dmastart(struct queue_entry *entry) { set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - rt2x00queue_index_inc(entry, Q_INDEX); + rt2x00queue_index_inc(entry->queue, Q_INDEX); } EXPORT_SYMBOL_GPL(rt2x00lib_dmastart); @@ -233,7 +230,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry) { set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags); clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); } EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); @@ -271,7 +268,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, /* * Remove L2 padding which was added during */ - if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags)) + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) rt2x00queue_remove_l2pad(entry->skb, header_length); /* @@ -280,7 +277,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * mac80211 will expect the same data to be present it the * frame as it was passed to us. */ - if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) rt2x00crypto_tx_insert_iv(entry->skb, header_length); /* @@ -353,14 +350,10 @@ void rt2x00lib_txdone(struct queue_entry *entry, * which would allow the rc algorithm to better decide on * which rates are suitable. */ - if (test_bit(TXDONE_AMPDU, &txdesc->flags) || - tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; tx_info->status.ampdu_len = 1; tx_info->status.ampdu_ack_len = success ? 1 : 0; - - if (!success) - tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; } if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { @@ -377,7 +370,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * send the status report back. */ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { - if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags)) + if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags)) ieee80211_tx_status(rt2x00dev->hw, entry->skb); else ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); @@ -392,7 +385,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->ops->lib->clear_entry(entry); - rt2x00queue_index_inc(entry, Q_INDEX_DONE); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* * If the data queue was below the threshold before the txdone @@ -518,6 +511,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry) (rxdesc.size > header_length) && (rxdesc.dev_flags & RXDONE_L2PAD)) rt2x00queue_remove_l2pad(entry->skb, header_length); + else + rt2x00queue_align_payload(entry->skb, header_length); /* Trim buffer to correct size */ skb_trim(entry->skb, rxdesc.size); @@ -559,7 +554,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry) submit_entry: entry->flags = 0; - rt2x00queue_index_inc(entry, Q_INDEX_DONE); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) rt2x00dev->ops->lib->clear_entry(entry); @@ -806,28 +801,23 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Take TX headroom required for alignment into account. */ - if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags)) + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE; - else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) + else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE; /* * Allocate tx status FIFO for driver use. */ - if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) { + if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) { /* - * Allocate the txstatus fifo. In the worst case the tx - * status fifo has to hold the tx status of all entries - * in all tx queues. Hence, calculate the kfifo size as - * tx_queues * entry_num and round up to the nearest - * power of 2. + * Allocate txstatus fifo and tasklet, we use a size of 512 + * for the kfifo which is big enough to store 512/4=128 tx + * status reports. In the worst case (tx status for all tx + * queues gets reported before we've got a chance to handle + * them) 24*4=384 tx status reports need to be cached. */ - int kfifo_size = - roundup_pow_of_two(rt2x00dev->ops->tx_queues * - rt2x00dev->ops->tx->entry_num * - sizeof(u32)); - - status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size, + status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512, GFP_KERNEL); if (status) return status; @@ -1071,7 +1061,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) /* * Stop all work. */ - del_timer_sync(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->intf_work); if (rt2x00_is_usb(rt2x00dev)) { cancel_work_sync(&rt2x00dev->rxdone_work); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00firmware.c b/trunk/drivers/net/wireless/rt2x00/rt2x00firmware.c index f316aad30612..be0ff78c1b16 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) { int retval; - if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags)) + if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) return 0; if (!rt2x00dev->fw) { diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00ht.c b/trunk/drivers/net/wireless/rt2x00/rt2x00ht.c new file mode 100644 index 000000000000..ae1219dffaae --- /dev/null +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -0,0 +1,133 @@ +/* + Copyright (C) 2004 - 2009 Ivo van Doorn + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00lib + Abstract: rt2x00 HT specific routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + + if (tx_info->control.sta) + txdesc->u.ht.mpdu_density = + tx_info->control.sta->ht_cap.ampdu_density; + + txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ + + txdesc->u.ht.stbc = + (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT; + + /* + * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the + * mcs rate to be used + */ + if (txrate->flags & IEEE80211_TX_RC_MCS) { + txdesc->u.ht.mcs = txrate->idx; + + /* + * MIMO PS should be set to 1 for STA's using dynamic SM PS + * when using more then one tx stream (>MCS7). + */ + if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && + ((tx_info->control.sta->ht_cap.cap & + IEEE80211_HT_CAP_SM_PS) >> + IEEE80211_HT_CAP_SM_PS_SHIFT) == + WLAN_HT_CAP_SM_PS_DYNAMIC) + __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); + } else { + txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txdesc->u.ht.mcs |= 0x08; + } + + /* + * This frame is eligible for an AMPDU, however, don't aggregate + * frames that are intended to probe a specific tx rate. + */ + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && + !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) + __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); + + /* + * Set 40Mhz mode if necessary (for legacy rates this will + * duplicate the frame to both channels). + */ + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || + txrate->flags & IEEE80211_TX_RC_DUP_DATA) + __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); + + /* + * Determine IFS values + * - Use TXOP_BACKOFF for management frames + * - Use TXOP_SIFS for fragment bursts + * - Use TXOP_HTTXOP for everything else + * + * Note: rt2800 devices won't use CTS protection (if used) + * for frames not transmitted with TXOP_HTTXOP + */ + if (ieee80211_is_mgmt(hdr->frame_control)) + txdesc->u.ht.txop = TXOP_BACKOFF; + else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) + txdesc->u.ht.txop = TXOP_SIFS; + else + txdesc->u.ht.txop = TXOP_HTTXOP; +} + +u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf) +{ + struct hw_mode_spec *spec = &rt2x00dev->spec; + int center_channel; + u16 i; + + /* + * Initialize center channel to current channel. + */ + center_channel = spec->channels[conf->channel->hw_value].channel; + + /* + * Adjust center channel to HT40+ and HT40- operation. + */ + if (conf_is_ht40_plus(conf)) + center_channel += 2; + else if (conf_is_ht40_minus(conf)) + center_channel -= (center_channel == 14) ? 1 : 2; + + for (i = 0; i < spec->num_channels; i++) + if (spec->channels[i].channel == center_channel) + return i; + + WARN_ON(1); + return conf->channel->hw_value; +} diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h b/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h index 322cc4f3de5d..2d94cbaf5f4a 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -32,7 +32,6 @@ */ #define WATCHDOG_INTERVAL round_jiffies_relative(HZ) #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) -#define AGC_INTERVAL round_jiffies_relative(4 * HZ) /* * rt2x00_rate: Per rate device information @@ -119,6 +118,16 @@ void rt2x00queue_free_skb(struct queue_entry *entry); */ void rt2x00queue_align_frame(struct sk_buff *skb); +/** + * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary + * @skb: The skb to align + * @header_length: Length of 802.11 header + * + * Align the 802.11 payload to a 4-byte boundary, this could + * mean the header is not aligned properly though. + */ +void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length); + /** * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary * @skb: The skb to align @@ -175,14 +184,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, /** * rt2x00queue_index_inc - Index incrementation function - * @entry: Queue entry (&struct queue_entry) to perform the action on. + * @queue: Queue (&struct data_queue) to perform the action on. * @index: Index type (&enum queue_index) to perform the action on. * - * This function will increase the requested index on the entry's queue, + * This function will increase the requested index on the queue, * it will grab the appropriate locks and handle queue overflow events by * resetting the index to the start of the queue. */ -void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index); +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); /** * rt2x00queue_init_queues - Initialize all data queues @@ -271,18 +280,6 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev); */ void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev); -/** - * rt2x00link_start_agc - Start periodic gain calibration - * @rt2x00dev: Pointer to &struct rt2x00_dev. - */ -void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00link_stop_agc - Stop periodic gain calibration - * @rt2x00dev: Pointer to &struct rt2x00_dev. - */ -void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev); - /** * rt2x00link_register - Initialize link tuning & watchdog functionality * @rt2x00dev: Pointer to &struct rt2x00_dev. @@ -387,18 +384,42 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, } #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +/* + * HT handlers. + */ +#ifdef CONFIG_RT2X00_LIB_HT +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate); + +u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf); +#else +static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ +} + +static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf) +{ + return conf->channel->hw_value; +} +#endif /* CONFIG_RT2X00_LIB_HT */ + /* * RFkill handlers. */ static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) { - if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy); } static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) { - if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00link.c b/trunk/drivers/net/wireless/rt2x00/rt2x00link.c index fa55399be192..c975b0a12e95 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00link.c @@ -192,7 +192,17 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) /* * Determine if software diversity is enabled for * either the TX or RX antenna (or both). + * Always perform this check since within the link + * tuner interval the configuration might have changed. */ + ant->flags &= ~ANTENNA_RX_DIVERSITY; + ant->flags &= ~ANTENNA_TX_DIVERSITY; + + if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) + ant->flags |= ANTENNA_RX_DIVERSITY; + if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) + ant->flags |= ANTENNA_TX_DIVERSITY; + if (!(ant->flags & ANTENNA_RX_DIVERSITY) && !(ant->flags & ANTENNA_TX_DIVERSITY)) { ant->flags = 0; @@ -373,7 +383,7 @@ static void rt2x00link_tuner(struct work_struct *work) * do not support link tuning at all, while other devices can disable * the feature from the EEPROM. */ - if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags)) + if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags)) rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); /* @@ -403,11 +413,12 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) { struct link *link = &rt2x00dev->link; - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - rt2x00dev->ops->lib->watchdog) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->watchdog_work, - WATCHDOG_INTERVAL); + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || + !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) + return; + + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->watchdog_work, WATCHDOG_INTERVAL); } void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) @@ -436,46 +447,8 @@ static void rt2x00link_watchdog(struct work_struct *work) WATCHDOG_INTERVAL); } -void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev) -{ - struct link *link = &rt2x00dev->link; - - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - rt2x00dev->ops->lib->gain_calibration) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->agc_work, - AGC_INTERVAL); -} - -void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) -{ - cancel_delayed_work_sync(&rt2x00dev->link.agc_work); -} - -static void rt2x00link_agc(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, link.agc_work.work); - struct link *link = &rt2x00dev->link; - - /* - * When the radio is shutting down we should - * immediately cease the watchdog monitoring. - */ - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - rt2x00dev->ops->lib->gain_calibration(rt2x00dev); - - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->agc_work, - AGC_INTERVAL); -} - void rt2x00link_register(struct rt2x00_dev *rt2x00dev) { - INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index 93bec140e598..661c6baad2b9 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * Use the ATIM queue if appropriate and present. */ if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && - test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) + test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) qid = QID_ATIM; queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); @@ -158,7 +158,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return; exit_fail: - rt2x00queue_pause_queue(queue); + ieee80211_stop_queue(rt2x00dev->hw, qid); dev_kfree_skb_any(skb); } EXPORT_SYMBOL_GPL(rt2x00mac_tx); @@ -411,11 +411,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, * of different types, but has no a separate filter for PS Poll frames, * FIF_CONTROL flag implies FIF_PSPOLL. */ - if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) { + if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) { if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) *total_flags |= FIF_CONTROL | FIF_PSPOLL; } - if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) { + if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) { if (*total_flags & FIF_CONTROL) *total_flags |= FIF_PSPOLL; } @@ -496,7 +496,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; - else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) + else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) return -EOPNOTSUPP; else if (key->keylen > 32) return -ENOSPC; @@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key); void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; - set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); + __set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); rt2x00link_stop_tuner(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); @@ -570,7 +570,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; - clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); + __clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); rt2x00link_start_tuner(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); @@ -737,84 +737,3 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) rt2x00queue_flush_queue(queue, drop); } EXPORT_SYMBOL_GPL(rt2x00mac_flush); - -int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct link_ant *ant = &rt2x00dev->link.ant; - struct antenna_setup *def = &rt2x00dev->default_ant; - struct antenna_setup setup; - - // The antenna value is not supposed to be 0, - // or exceed the maximum number of antenna's. - if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3)) - return -EINVAL; - - // When the client tried to configure the antenna to or from - // diversity mode, we must reset the default antenna as well - // as that controls the diversity switch. - if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3) - ant->flags &= ~ANTENNA_TX_DIVERSITY; - if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3) - ant->flags &= ~ANTENNA_RX_DIVERSITY; - - // If diversity is being enabled, check if we need hardware - // or software diversity. In the latter case, reset the value, - // and make sure we update the antenna flags to have the - // link tuner pick up the diversity tuning. - if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) { - tx_ant = ANTENNA_SW_DIVERSITY; - ant->flags |= ANTENNA_TX_DIVERSITY; - } - - if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) { - rx_ant = ANTENNA_SW_DIVERSITY; - ant->flags |= ANTENNA_RX_DIVERSITY; - } - - setup.tx = tx_ant; - setup.rx = rx_ant; - - rt2x00lib_config_antenna(rt2x00dev, setup); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna); - -int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct link_ant *ant = &rt2x00dev->link.ant; - struct antenna_setup *active = &rt2x00dev->link.ant.active; - - // When software diversity is active, we must report this to the - // client and not the current active antenna state. - if (ant->flags & ANTENNA_TX_DIVERSITY) - *tx_ant = ANTENNA_HW_DIVERSITY; - else - *tx_ant = active->tx; - - if (ant->flags & ANTENNA_RX_DIVERSITY) - *rx_ant = ANTENNA_HW_DIVERSITY; - else - *rx_ant = active->rx; - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna); - -void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, - u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_queue *queue; - - tx_queue_for_each(rt2x00dev, queue) { - *tx += queue->length; - *tx_max += queue->limit; - } - - *rx = rt2x00dev->rx->length; - *rx_max = rt2x00dev->rx->limit; -} -EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c index 17148bb24426..4dd82b0b0520 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -60,15 +60,14 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); -bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) +void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue = rt2x00dev->rx; struct queue_entry *entry; struct queue_entry_priv_pci *entry_priv; struct skb_frame_desc *skbdesc; - int max_rx = 16; - while (--max_rx) { + while (1) { entry = rt2x00queue_get_entry(queue, Q_INDEX); entry_priv = entry->priv_data; @@ -94,20 +93,9 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) */ rt2x00lib_rxdone(entry); } - - return !max_rx; } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); -void rt2x00pci_flush_queue(struct data_queue *queue, bool drop) -{ - unsigned int i; - - for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) - msleep(10); -} -EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue); - /* * Device initialization handlers. */ @@ -251,8 +239,9 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) return -ENOMEM; } -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { + struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data; struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h index e2c99f2b9a14..746ce8fe8cf4 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -101,21 +101,8 @@ struct queue_entry_priv_pci { /** * rt2x00pci_rxdone - Handle RX done events * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * - * Returns true if there are still rx frames pending and false if all - * pending rx frames were processed. - */ -bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00pci_flush_queue - Flush data queue - * @queue: Data queue to stop - * @drop: True to drop all pending frames. - * - * This will wait for a maximum of 100ms, waiting for the queues - * to become empty. */ -void rt2x00pci_flush_queue(struct data_queue *queue, bool drop); +void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); /* * Device initialization handlers. @@ -126,7 +113,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); /* * PCI driver handlers. */ -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops); +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); void rt2x00pci_remove(struct pci_dev *pci_dev); #ifdef CONFIG_PM int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c index 56f9d0df9c61..4b3c70eeef1f 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry) * at least 8 bytes bytes available in headroom for IV/EIV * and 8 bytes for ICV data as tailroon. */ - if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { head_size += 8; tail_size += 8; } @@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry) memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; - if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) { + if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, @@ -148,6 +148,19 @@ void rt2x00queue_align_frame(struct sk_buff *skb) skb_trim(skb, frame_length); } +void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) +{ + unsigned int frame_length = skb->len; + unsigned int align = ALIGN_SIZE(skb, header_length); + + if (!align) + return; + + skb_push(skb, align); + memmove(skb->data, skb->data + align, frame_length); + skb_trim(skb, frame_length); +} + void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) { unsigned int payload_length = skb->len - header_length; @@ -213,7 +226,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); - if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags)) + if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags)) return; /* @@ -302,85 +315,6 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, } } -static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - - if (tx_info->control.sta) - txdesc->u.ht.mpdu_density = - tx_info->control.sta->ht_cap.ampdu_density; - - txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ - - /* - * Only one STBC stream is supported for now. - */ - if (tx_info->flags & IEEE80211_TX_CTL_STBC) - txdesc->u.ht.stbc = 1; - - /* - * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the - * mcs rate to be used - */ - if (txrate->flags & IEEE80211_TX_RC_MCS) { - txdesc->u.ht.mcs = txrate->idx; - - /* - * MIMO PS should be set to 1 for STA's using dynamic SM PS - * when using more then one tx stream (>MCS7). - */ - if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && - ((tx_info->control.sta->ht_cap.cap & - IEEE80211_HT_CAP_SM_PS) >> - IEEE80211_HT_CAP_SM_PS_SHIFT) == - WLAN_HT_CAP_SM_PS_DYNAMIC) - __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); - } else { - txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txdesc->u.ht.mcs |= 0x08; - } - - /* - * This frame is eligible for an AMPDU, however, don't aggregate - * frames that are intended to probe a specific tx rate. - */ - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && - !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) - __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); - - /* - * Set 40Mhz mode if necessary (for legacy rates this will - * duplicate the frame to both channels). - */ - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || - txrate->flags & IEEE80211_TX_RC_DUP_DATA) - __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); - if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) - __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); - - /* - * Determine IFS values - * - Use TXOP_BACKOFF for management frames except beacons - * - Use TXOP_SIFS for fragment bursts - * - Use TXOP_HTTXOP for everything else - * - * Note: rt2800 devices won't use CTS protection (if used) - * for frames not transmitted with TXOP_HTTXOP - */ - if (ieee80211_is_mgmt(hdr->frame_control) && - !ieee80211_is_beacon(hdr->frame_control)) - txdesc->u.ht.txop = TXOP_BACKOFF; - else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) - txdesc->u.ht.txop = TXOP_SIFS; - else - txdesc->u.ht.txop = TXOP_HTTXOP; -} - static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { @@ -475,8 +409,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, rt2x00crypto_create_tx_descriptor(entry, txdesc); rt2x00queue_create_tx_descriptor_seq(entry, txdesc); - if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) - rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate); + if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags)) + rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); else rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); } @@ -515,7 +449,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry, /* * Map the skb to DMA. */ - if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) + if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) rt2x00queue_map_txskb(entry); return 0; @@ -561,11 +495,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, struct skb_frame_desc *skbdesc; u8 rate_idx, rate_flags; - if (unlikely(rt2x00queue_full(queue))) { - ERROR(queue->rt2x00dev, - "Dropping frame due to full tx queue %d.\n", queue->qid); + if (unlikely(rt2x00queue_full(queue))) return -ENOBUFS; - } if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))) { @@ -608,7 +539,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { - if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags)) + if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) rt2x00crypto_tx_copy_iv(skb, &txdesc); else rt2x00crypto_tx_remove_iv(skb, &txdesc); @@ -622,9 +553,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, * PCI and USB devices, while header alignment only is valid * for PCI devices. */ - if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags)) + if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); - else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags)) + else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) rt2x00queue_align_frame(entry->skb); /* @@ -640,7 +571,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, set_bit(ENTRY_DATA_PENDING, &entry->flags); - rt2x00queue_index_inc(entry, Q_INDEX); + rt2x00queue_index_inc(queue, Q_INDEX); rt2x00queue_write_tx_descriptor(entry, &txdesc); rt2x00queue_kick_tx_queue(queue, &txdesc); @@ -729,12 +660,10 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, return ret; } -bool rt2x00queue_for_each_entry(struct data_queue *queue, +void rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - void *data, - bool (*fn)(struct queue_entry *entry, - void *data)) + void (*fn)(struct queue_entry *entry)) { unsigned long irqflags; unsigned int index_start; @@ -745,7 +674,7 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue, ERROR(queue->rt2x00dev, "Entry requested from invalid index range (%d - %d)\n", start, end); - return true; + return; } /* @@ -764,23 +693,15 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue, * send out all frames in the correct order. */ if (index_start < index_end) { - for (i = index_start; i < index_end; i++) { - if (fn(&queue->entries[i], data)) - return true; - } + for (i = index_start; i < index_end; i++) + fn(&queue->entries[i]); } else { - for (i = index_start; i < queue->limit; i++) { - if (fn(&queue->entries[i], data)) - return true; - } + for (i = index_start; i < queue->limit; i++) + fn(&queue->entries[i]); - for (i = 0; i < index_end; i++) { - if (fn(&queue->entries[i], data)) - return true; - } + for (i = 0; i < index_end; i++) + fn(&queue->entries[i]); } - - return false; } EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry); @@ -806,9 +727,8 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, } EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); -void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index) +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) { - struct data_queue *queue = entry->queue; unsigned long irqflags; if (unlikely(index >= Q_INDEX_MAX)) { @@ -823,7 +743,7 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index) if (queue->index[index] >= queue->limit) queue->index[index] = 0; - entry->last_action = jiffies; + queue->last_action[index] = jiffies; if (index == Q_INDEX) { queue->length++; @@ -928,6 +848,7 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) { + unsigned int i; bool started; bool tx_queue = (queue->qid == QID_AC_VO) || @@ -962,12 +883,20 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) } /* - * Check if driver supports flushing, if that is the case we can - * defer the flushing to the driver. Otherwise we must use the - * alternative which just waits for the queue to become empty. + * Check if driver supports flushing, we can only guarentee + * full support for flushing if the driver is able + * to cancel all pending frames (drop = true). + */ + if (drop && queue->rt2x00dev->ops->lib->flush_queue) + queue->rt2x00dev->ops->lib->flush_queue(queue); + + /* + * When we don't want to drop any frames, or when + * the driver doesn't fully flush the queue correcly, + * we must wait for the queue to become empty. */ - if (likely(queue->rt2x00dev->ops->lib->flush_queue)) - queue->rt2x00dev->ops->lib->flush_queue(queue, drop); + for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++) + msleep(10); /* * The queue flush has failed... @@ -1040,8 +969,10 @@ static void rt2x00queue_reset(struct data_queue *queue) queue->count = 0; queue->length = 0; - for (i = 0; i < Q_INDEX_MAX; i++) + for (i = 0; i < Q_INDEX_MAX; i++) { queue->index[i] = 0; + queue->last_action[i] = jiffies; + } spin_unlock_irqrestore(&queue->index_lock, irqflags); } @@ -1148,7 +1079,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) if (status) goto exit; - if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) { + if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { status = rt2x00queue_alloc_entries(rt2x00dev->atim, rt2x00dev->ops->atim); if (status) @@ -1200,7 +1131,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; enum data_queue_qid qid; unsigned int req_atim = - !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); + !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); /* * We need the following queues: diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h index 36f4d03eff61..0c8b0c699679 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -217,7 +217,6 @@ enum txdone_entry_desc_flags { TXDONE_FALLBACK, TXDONE_FAILURE, TXDONE_EXCESSIVE_RETRY, - TXDONE_AMPDU, }; /** @@ -364,7 +363,6 @@ enum queue_entry_flags { * struct queue_entry: Entry inside the &struct data_queue * * @flags: Entry flags, see &enum queue_entry_flags. - * @last_action: Timestamp of last change. * @queue: The data queue (&struct data_queue) to which this entry belongs. * @skb: The buffer which is currently being transmitted (for TX queue), * or used to directly recieve data in (for RX queue). @@ -374,7 +372,6 @@ enum queue_entry_flags { */ struct queue_entry { unsigned long flags; - unsigned long last_action; struct data_queue *queue; @@ -465,6 +462,7 @@ struct data_queue { unsigned short threshold; unsigned short length; unsigned short index[Q_INDEX_MAX]; + unsigned long last_action[Q_INDEX_MAX]; unsigned short txop; unsigned short aifs; @@ -581,22 +579,16 @@ struct data_queue_desc { * @queue: Pointer to @data_queue * @start: &enum queue_index Pointer to start index * @end: &enum queue_index Pointer to end index - * @data: Data to pass to the callback function * @fn: The function to call for each &struct queue_entry * * This will walk through all entries in the queue, in chronological * order. This means it will start at the current @start pointer * and will walk through the queue until it reaches the @end pointer. - * - * If fn returns true for an entry rt2x00queue_for_each_entry will stop - * processing and return true as well. */ -bool rt2x00queue_for_each_entry(struct data_queue *queue, +void rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - void *data, - bool (*fn)(struct queue_entry *entry, - void *data)); + void (*fn)(struct queue_entry *entry)); /** * rt2x00queue_empty - Check if the queue is empty. @@ -636,24 +628,22 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) /** * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports - * @entry: Queue entry to check. + * @queue: Queue to check. */ -static inline int rt2x00queue_status_timeout(struct queue_entry *entry) +static inline int rt2x00queue_status_timeout(struct data_queue *queue) { - if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return false; - return time_after(jiffies, entry->last_action + msecs_to_jiffies(100)); + return time_after(queue->last_action[Q_INDEX_DMA_DONE], + queue->last_action[Q_INDEX_DONE] + (HZ / 10)); } /** - * rt2x00queuedma__timeout - Check if a timeout occured for DMA transfers - * @entry: Queue entry to check. + * rt2x00queue_timeout - Check if a timeout occured for DMA transfers + * @queue: Queue to check. */ -static inline int rt2x00queue_dma_timeout(struct queue_entry *entry) +static inline int rt2x00queue_dma_timeout(struct data_queue *queue) { - if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return false; - return time_after(jiffies, entry->last_action + msecs_to_jiffies(100)); + return time_after(queue->last_action[Q_INDEX], + queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10)); } /** diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c index 570184ee163c..fbe735f5b352 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -165,56 +165,6 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); - -struct rt2x00_async_read_data { - __le32 reg; - struct usb_ctrlrequest cr; - struct rt2x00_dev *rt2x00dev; - void (*callback)(struct rt2x00_dev *,int,u32); -}; - -static void rt2x00usb_register_read_async_cb(struct urb *urb) -{ - struct rt2x00_async_read_data *rd = urb->context; - rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); - kfree(urb->context); -} - -void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void (*callback)(struct rt2x00_dev*,int,u32)) -{ - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); - struct urb *urb; - struct rt2x00_async_read_data *rd; - - rd = kmalloc(sizeof(*rd), GFP_ATOMIC); - if (!rd) - return; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(rd); - return; - } - - rd->rt2x00dev = rt2x00dev; - rd->callback = callback; - rd->cr.bRequestType = USB_VENDOR_REQUEST_IN; - rd->cr.bRequest = USB_MULTI_READ; - rd->cr.wValue = 0; - rd->cr.wIndex = cpu_to_le16(offset); - rd->cr.wLength = cpu_to_le16(sizeof(u32)); - - usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), - (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), - rt2x00usb_register_read_async_cb, rd); - if (usb_submit_urb(urb, GFP_ATOMIC) < 0) - kfree(rd); - usb_free_urb(urb); -} -EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async); - /* * TX data handlers. */ @@ -262,9 +212,6 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; - if (rt2x00dev->ops->lib->tx_dma_done) - rt2x00dev->ops->lib->tx_dma_done(entry); - /* * Report the frame as DMA done */ @@ -280,12 +227,10 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Schedule the delayed work for reading the TX status * from the device. */ - if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) || - !kfifo_is_empty(&rt2x00dev->txstatus_fifo)) - queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } -static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) +static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -295,7 +240,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return true; + return; /* * USB devices cannot blindly pass the skb->len as the @@ -316,8 +261,6 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } - - return false; } /* @@ -380,7 +323,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); } -static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) +static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -389,7 +332,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return true; + return; rt2x00lib_dmastart(entry); @@ -405,8 +348,6 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } - - return false; } void rt2x00usb_kick_queue(struct data_queue *queue) @@ -417,18 +358,12 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_AC_BE: case QID_AC_BK: if (!rt2x00queue_empty(queue)) - rt2x00queue_for_each_entry(queue, - Q_INDEX_DONE, - Q_INDEX, - NULL, + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, rt2x00usb_kick_tx_entry); break; case QID_RX: if (!rt2x00queue_full(queue)) - rt2x00queue_for_each_entry(queue, - Q_INDEX_DONE, - Q_INDEX, - NULL, + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, rt2x00usb_kick_rx_entry); break; default: @@ -437,14 +372,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); -static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) +static void rt2x00usb_flush_entry(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv = entry->priv_data; struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return true; + return; usb_kill_urb(entry_priv->urb); @@ -452,20 +387,17 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) * Kill guardian urb (if required by driver). */ if ((entry->queue->qid == QID_BEACON) && - (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))) + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) usb_kill_urb(bcn_priv->guardian_urb); - - return false; } -void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) +void rt2x00usb_flush_queue(struct data_queue *queue) { struct work_struct *completion; unsigned int i; - if (drop) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, - rt2x00usb_flush_entry); + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_flush_entry); /* * Obtain the queue completion handler @@ -484,7 +416,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) return; } - for (i = 0; i < 10; i++) { + for (i = 0; i < 20; i++) { /* * Check if the driver is already done, otherwise we * have to sleep a little while to give the driver/hw @@ -524,31 +456,15 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); } -static int rt2x00usb_status_timeout(struct data_queue *queue) -{ - struct queue_entry *entry; - - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - return rt2x00queue_status_timeout(entry); -} - -static int rt2x00usb_dma_timeout(struct data_queue *queue) -{ - struct queue_entry *entry; - - entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); - return rt2x00queue_dma_timeout(entry); -} - void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; tx_queue_for_each(rt2x00dev, queue) { if (!rt2x00queue_empty(queue)) { - if (rt2x00usb_dma_timeout(queue)) + if (rt2x00queue_dma_timeout(queue)) rt2x00usb_watchdog_tx_dma(queue); - if (rt2x00usb_status_timeout(queue)) + if (rt2x00queue_status_timeout(queue)) rt2x00usb_watchdog_tx_status(queue); } } @@ -573,7 +489,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) entry->flags = 0; if (entry->queue->qid == QID_RX) - rt2x00usb_kick_rx_entry(entry, NULL); + rt2x00usb_kick_rx_entry(entry); } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); @@ -667,7 +583,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue) * then we are done. */ if (queue->qid != QID_BEACON || - !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)) + !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) return 0; for (i = 0; i < queue->limit; i++) { @@ -702,7 +618,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue) * then we are done. */ if (queue->qid != QID_BEACON || - !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)) + !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) return; for (i = 0; i < queue->limit; i++) { @@ -791,9 +707,10 @@ static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev) } int rt2x00usb_probe(struct usb_interface *usb_intf, - const struct rt2x00_ops *ops) + const struct usb_device_id *id) { struct usb_device *usb_dev = interface_to_usbdev(usb_intf); + struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info; struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; @@ -818,7 +735,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); - init_timer(&rt2x00dev->txstatus_timer); retval = rt2x00usb_alloc_reg(rt2x00dev); if (retval) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h index 52b09d2e11de..6aaf51fc7ad8 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -34,6 +34,12 @@ interface_to_usbdev(intf); \ }) +/* + * This variable should be used with the + * usb_driver structure initialization. + */ +#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops) + /* * For USB vendor requests we need to pass a timeout * time in ms, for this we use the REGISTER_TIMEOUT, @@ -339,21 +345,6 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, const struct rt2x00_field32 field, u32 *reg); -/** - * rt2x00usb_register_read_async - Asynchronously read 32bit register word - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @callback: Functon to call when read completes. - * - * Submit a control URB to read a 32bit register. This safe to - * be called from atomic context. The callback will be called - * when the URB completes. Otherwise the function is similar - * to rt2x00usb_register_read(). - */ -void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void (*callback)(struct rt2x00_dev*,int,u32)); - /* * Radio handlers */ @@ -398,13 +389,11 @@ void rt2x00usb_kick_queue(struct data_queue *queue); /** * rt2x00usb_flush_queue - Flush data queue * @queue: Data queue to stop - * @drop: True to drop all pending frames. * - * This will walk through all entries of the queue and will optionally - * kill all URB's which were send to the device, or at least wait until - * they have been returned from the device.. + * This will walk through all entries of the queue and kill all + * URB's which were send to the device. */ -void rt2x00usb_flush_queue(struct data_queue *queue, bool drop); +void rt2x00usb_flush_queue(struct data_queue *queue); /** * rt2x00usb_watchdog - Watchdog for USB communication @@ -427,7 +416,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); * USB driver handlers. */ int rt2x00usb_probe(struct usb_interface *usb_intf, - const struct rt2x00_ops *ops); + const struct usb_device_id *id); void rt2x00usb_disconnect(struct usb_interface *usb_intf); #ifdef CONFIG_PM int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state); diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c index 9d35ec16a3a5..77e8113b91e1 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c @@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); + !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); /* * Configure the RX antenna. @@ -811,10 +811,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; - lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); + lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); } else { sel = antenna_sel_bg; - lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); + lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); } for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -834,7 +834,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, else if (rt2x00_rf(rt2x00dev, RF2527)) rt61pci_config_antenna_2x(rt2x00dev, ant); else if (rt2x00_rf(rt2x00dev, RF2529)) { - if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) rt61pci_config_antenna_2x(rt2x00dev, ant); else rt61pci_config_antenna_2529(rt2x00dev, ant); @@ -848,13 +848,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, short lna_gain = 0; if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) lna_gain += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); } else { - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) lna_gain += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); @@ -1050,14 +1050,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { low_bound += 0x10; up_bound += 0x10; } } else { low_bound = 0x20; up_bound = 0x40; - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { low_bound += 0x10; up_bound += 0x10; } @@ -2260,8 +2260,8 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } -static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, - struct rt2x00_field32 irq_field) +static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, + struct rt2x00_field32 irq_field) { u32 reg; @@ -2313,10 +2313,8 @@ static void rt61pci_tbtt_tasklet(unsigned long data) static void rt61pci_rxdone_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - if (rt2x00pci_rxdone(rt2x00dev)) - rt2x00pci_rxdone(rt2x00dev); - else - rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); + rt2x00pci_rxdone(rt2x00dev); + rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); } static void rt61pci_autowake_tasklet(unsigned long data) @@ -2537,7 +2535,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Determine number of antennas. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) - __set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags); + __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); /* * Identify default antenna configuration. @@ -2551,20 +2549,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Read the Frame type. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) - __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags); + __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); /* * Detect if this device has a hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Read frequency offset and RF programming sequence. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ)) - __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags); + __set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags); rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); @@ -2574,9 +2572,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) - __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); + __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) - __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); + __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); /* * When working with a RF2529 chip without double antenna, @@ -2584,7 +2582,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * eeprom word. */ if (rt2x00_rf(rt2x00dev, RF2529) && - !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) { + !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { rt2x00dev->default_ant.rx = ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); rt2x00dev->default_ant.tx = @@ -2799,7 +2797,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) { + if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { spec->num_channels = 14; spec->channels = rf_vals_noseq; } else { @@ -2869,16 +2867,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames, * but has no a separate filter for PS Poll frames. */ - __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); /* * This device requires firmware and DMA mapped skbs. */ - __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); - __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); if (!modparam_nohwcrypt) - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2979,9 +2977,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, - .set_antenna = rt2x00mac_set_antenna, - .get_antenna = rt2x00mac_get_antenna, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -3006,7 +3001,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .start_queue = rt61pci_start_queue, .kick_queue = rt61pci_kick_queue, .stop_queue = rt61pci_stop_queue, - .flush_queue = rt2x00pci_flush_queue, .write_tx_desc = rt61pci_write_tx_desc, .write_beacon = rt61pci_write_beacon, .clear_beacon = rt61pci_clear_beacon, @@ -3064,11 +3058,11 @@ static const struct rt2x00_ops rt61pci_ops = { */ static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = { /* RT2561s */ - { PCI_DEVICE(0x1814, 0x0301) }, + { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) }, /* RT2561 v2 */ - { PCI_DEVICE(0x1814, 0x0302) }, + { PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) }, /* RT2661 */ - { PCI_DEVICE(0x1814, 0x0401) }, + { PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) }, { 0, } }; @@ -3083,16 +3077,10 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s); MODULE_FIRMWARE(FIRMWARE_RT2661); MODULE_LICENSE("GPL"); -static int rt61pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) -{ - return rt2x00pci_probe(pci_dev, &rt61pci_ops); -} - static struct pci_driver rt61pci_driver = { .name = KBUILD_MODNAME, .id_table = rt61pci_device_table, - .probe = rt61pci_probe, + .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index a6ce7d6cbdfa..02f1148c577e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, switch (ant->rx) { case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); - temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags) + temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); break; @@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); + !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); /* * Configure the RX antenna. @@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; - lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); + lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); } else { sel = antenna_sel_bg; - lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); + lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); } for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, short lna_gain = 0; if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) lna_gain += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); @@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, low_bound = 0x28; up_bound = 0x48; - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { low_bound += 0x10; up_bound += 0x10; } @@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, up_bound = 0x1c; } - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { low_bound += 0x14; up_bound += 0x10; } @@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) } if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { if (lna == 3 || lna == 2) offset += 10; } else { @@ -1899,13 +1899,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Read the Frame type. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) - __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags); + __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); /* * Detect if this device has an hardware controlled radio. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Read frequency offset. @@ -1919,8 +1919,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) { - __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); + __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); } /* @@ -2200,15 +2200,16 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device has multiple filters for control frames, * but has no a separate filter for PS Poll frames. */ - __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); + __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); /* * This device requires firmware. */ - __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); if (!modparam_nohwcrypt) - __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); - __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); + __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2310,9 +2311,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .flush = rt2x00mac_flush, - .set_antenna = rt2x00mac_set_antenna, - .get_antenna = rt2x00mac_get_antenna, - .get_ringparam = rt2x00mac_get_ringparam, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2391,113 +2389,114 @@ static const struct rt2x00_ops rt73usb_ops = { */ static struct usb_device_id rt73usb_device_table[] = { /* AboCom */ - { USB_DEVICE(0x07b8, 0xb21b) }, - { USB_DEVICE(0x07b8, 0xb21c) }, - { USB_DEVICE(0x07b8, 0xb21d) }, - { USB_DEVICE(0x07b8, 0xb21e) }, - { USB_DEVICE(0x07b8, 0xb21f) }, + { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) }, /* AL */ - { USB_DEVICE(0x14b2, 0x3c10) }, + { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) }, /* Amigo */ - { USB_DEVICE(0x148f, 0x9021) }, - { USB_DEVICE(0x0eb0, 0x9021) }, + { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, /* AMIT */ - { USB_DEVICE(0x18c5, 0x0002) }, + { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) }, /* Askey */ - { USB_DEVICE(0x1690, 0x0722) }, + { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) }, /* ASUS */ - { USB_DEVICE(0x0b05, 0x1723) }, - { USB_DEVICE(0x0b05, 0x1724) }, + { USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) }, /* Belkin */ - { USB_DEVICE(0x050d, 0x705a) }, - { USB_DEVICE(0x050d, 0x905b) }, - { USB_DEVICE(0x050d, 0x905c) }, + { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, /* Billionton */ - { USB_DEVICE(0x1631, 0xc019) }, - { USB_DEVICE(0x08dd, 0x0120) }, + { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, /* Buffalo */ - { USB_DEVICE(0x0411, 0x00d8) }, - { USB_DEVICE(0x0411, 0x00d9) }, - { USB_DEVICE(0x0411, 0x00f4) }, - { USB_DEVICE(0x0411, 0x0116) }, - { USB_DEVICE(0x0411, 0x0119) }, - { USB_DEVICE(0x0411, 0x0137) }, + { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) }, /* CEIVA */ - { USB_DEVICE(0x178d, 0x02be) }, + { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ - { USB_DEVICE(0x1371, 0x9022) }, - { USB_DEVICE(0x1371, 0x9032) }, + { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c22) }, + { USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) }, /* Corega */ - { USB_DEVICE(0x07aa, 0x002e) }, + { USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) }, /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c03) }, - { USB_DEVICE(0x07d1, 0x3c04) }, - { USB_DEVICE(0x07d1, 0x3c06) }, - { USB_DEVICE(0x07d1, 0x3c07) }, + { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, /* Edimax */ - { USB_DEVICE(0x7392, 0x7318) }, - { USB_DEVICE(0x7392, 0x7618) }, + { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) }, /* EnGenius */ - { USB_DEVICE(0x1740, 0x3701) }, + { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) }, /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0004) }, + { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x8008) }, - { USB_DEVICE(0x1044, 0x800a) }, + { USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) }, /* Huawei-3Com */ - { USB_DEVICE(0x1472, 0x0009) }, + { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) }, /* Hercules */ - { USB_DEVICE(0x06f8, 0xe002) }, - { USB_DEVICE(0x06f8, 0xe010) }, - { USB_DEVICE(0x06f8, 0xe020) }, + { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) }, /* Linksys */ - { USB_DEVICE(0x13b1, 0x0020) }, - { USB_DEVICE(0x13b1, 0x0023) }, - { USB_DEVICE(0x13b1, 0x0028) }, + { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x4600) }, - { USB_DEVICE(0x0db0, 0x6877) }, - { USB_DEVICE(0x0db0, 0x6874) }, - { USB_DEVICE(0x0db0, 0xa861) }, - { USB_DEVICE(0x0db0, 0xa874) }, + { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ovislink */ - { USB_DEVICE(0x1b75, 0x7318) }, + { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ralink */ - { USB_DEVICE(0x04bb, 0x093d) }, - { USB_DEVICE(0x148f, 0x2573) }, - { USB_DEVICE(0x148f, 0x2671) }, - { USB_DEVICE(0x0812, 0x3101) }, + { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) }, /* Qcom */ - { USB_DEVICE(0x18e8, 0x6196) }, - { USB_DEVICE(0x18e8, 0x6229) }, - { USB_DEVICE(0x18e8, 0x6238) }, + { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) }, /* Samsung */ - { USB_DEVICE(0x04e8, 0x4471) }, + { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) }, /* Senao */ - { USB_DEVICE(0x1740, 0x7100) }, + { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0024) }, - { USB_DEVICE(0x0df6, 0x0027) }, - { USB_DEVICE(0x0df6, 0x002f) }, - { USB_DEVICE(0x0df6, 0x90ac) }, - { USB_DEVICE(0x0df6, 0x9712) }, + { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, /* Surecom */ - { USB_DEVICE(0x0769, 0x31f3) }, + { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, /* Tilgin */ - { USB_DEVICE(0x6933, 0x5001) }, + { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) }, /* Philips */ - { USB_DEVICE(0x0471, 0x200a) }, + { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, /* Planex */ - { USB_DEVICE(0x2019, 0xab01) }, - { USB_DEVICE(0x2019, 0xab50) }, + { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, /* WideTell */ - { USB_DEVICE(0x7167, 0x3840) }, + { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, /* Zcom */ - { USB_DEVICE(0x0cde, 0x001c) }, + { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, /* ZyXEL */ - { USB_DEVICE(0x0586, 0x3415) }, + { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) }, { 0, } }; @@ -2509,16 +2508,10 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table); MODULE_FIRMWARE(FIRMWARE_RT2571); MODULE_LICENSE("GPL"); -static int rt73usb_probe(struct usb_interface *usb_intf, - const struct usb_device_id *id) -{ - return rt2x00usb_probe(usb_intf, &rt73usb_ops); -} - static struct usb_driver rt73usb_driver = { .name = KBUILD_MODNAME, .id_table = rt73usb_device_table, - .probe = rt73usb_probe, + .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, diff --git a/trunk/drivers/net/wireless/rtlwifi/base.c b/trunk/drivers/net/wireless/rtlwifi/base.c index d3666573d6b8..bb0c781f4a1b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/base.c +++ b/trunk/drivers/net/wireless/rtlwifi/base.c @@ -50,9 +50,8 @@ *3) functions called by core.c *4) wq & timer callback functions *5) frame process functions - *6) IOT functions - *7) sysfs functions - *8) ... + *6) sysfs functions + *7) ... */ /********************************************************* @@ -60,7 +59,7 @@ * mac80211 init functions * *********************************************************/ -static struct ieee80211_channel rtl_channeltable_2g[] = { +static struct ieee80211_channel rtl_channeltable[] = { {.center_freq = 2412, .hw_value = 1,}, {.center_freq = 2417, .hw_value = 2,}, {.center_freq = 2422, .hw_value = 3,}, @@ -77,34 +76,7 @@ static struct ieee80211_channel rtl_channeltable_2g[] = { {.center_freq = 2484, .hw_value = 14,}, }; -static struct ieee80211_channel rtl_channeltable_5g[] = { - {.center_freq = 5180, .hw_value = 36,}, - {.center_freq = 5200, .hw_value = 40,}, - {.center_freq = 5220, .hw_value = 44,}, - {.center_freq = 5240, .hw_value = 48,}, - {.center_freq = 5260, .hw_value = 52,}, - {.center_freq = 5280, .hw_value = 56,}, - {.center_freq = 5300, .hw_value = 60,}, - {.center_freq = 5320, .hw_value = 64,}, - {.center_freq = 5500, .hw_value = 100,}, - {.center_freq = 5520, .hw_value = 104,}, - {.center_freq = 5540, .hw_value = 108,}, - {.center_freq = 5560, .hw_value = 112,}, - {.center_freq = 5580, .hw_value = 116,}, - {.center_freq = 5600, .hw_value = 120,}, - {.center_freq = 5620, .hw_value = 124,}, - {.center_freq = 5640, .hw_value = 128,}, - {.center_freq = 5660, .hw_value = 132,}, - {.center_freq = 5680, .hw_value = 136,}, - {.center_freq = 5700, .hw_value = 140,}, - {.center_freq = 5745, .hw_value = 149,}, - {.center_freq = 5765, .hw_value = 153,}, - {.center_freq = 5785, .hw_value = 157,}, - {.center_freq = 5805, .hw_value = 161,}, - {.center_freq = 5825, .hw_value = 165,}, -}; - -static struct ieee80211_rate rtl_ratetable_2g[] = { +static struct ieee80211_rate rtl_ratetable[] = { {.bitrate = 10, .hw_value = 0x00,}, {.bitrate = 20, .hw_value = 0x01,}, {.bitrate = 55, .hw_value = 0x02,}, @@ -119,57 +91,18 @@ static struct ieee80211_rate rtl_ratetable_2g[] = { {.bitrate = 540, .hw_value = 0x0b,}, }; -static struct ieee80211_rate rtl_ratetable_5g[] = { - {.bitrate = 60, .hw_value = 0x04,}, - {.bitrate = 90, .hw_value = 0x05,}, - {.bitrate = 120, .hw_value = 0x06,}, - {.bitrate = 180, .hw_value = 0x07,}, - {.bitrate = 240, .hw_value = 0x08,}, - {.bitrate = 360, .hw_value = 0x09,}, - {.bitrate = 480, .hw_value = 0x0a,}, - {.bitrate = 540, .hw_value = 0x0b,}, -}; - static const struct ieee80211_supported_band rtl_band_2ghz = { .band = IEEE80211_BAND_2GHZ, - .channels = rtl_channeltable_2g, - .n_channels = ARRAY_SIZE(rtl_channeltable_2g), + .channels = rtl_channeltable, + .n_channels = ARRAY_SIZE(rtl_channeltable), - .bitrates = rtl_ratetable_2g, - .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), + .bitrates = rtl_ratetable, + .n_bitrates = ARRAY_SIZE(rtl_ratetable), .ht_cap = {0}, }; -static struct ieee80211_supported_band rtl_band_5ghz = { - .band = IEEE80211_BAND_5GHZ, - - .channels = rtl_channeltable_5g, - .n_channels = ARRAY_SIZE(rtl_channeltable_5g), - - .bitrates = rtl_ratetable_5g, - .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), - - .ht_cap = {0}, -}; - -static const u8 tid_to_ac[] = { - 2, /* IEEE80211_AC_BE */ - 3, /* IEEE80211_AC_BK */ - 3, /* IEEE80211_AC_BK */ - 2, /* IEEE80211_AC_BE */ - 1, /* IEEE80211_AC_VI */ - 1, /* IEEE80211_AC_VI */ - 0, /* IEEE80211_AC_VO */ - 0, /* IEEE80211_AC_VO */ -}; - -u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid) -{ - return tid_to_ac[tid]; -} - static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, struct ieee80211_sta_ht_cap *ht_cap) { @@ -182,9 +115,6 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; - if (rtlpriv->rtlhal.disable_amsdu_8k) - ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; - /* *Maximum length of AMPDU that the STA can receive. *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) @@ -229,99 +159,37 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, static void _rtl_init_mac80211(struct ieee80211_hw *hw) { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct ieee80211_supported_band *sband; + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == - BAND_ON_BOTH) { - /* 1: 2.4 G bands */ - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - - /* 2: 5 G bands */ - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + /* + * <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) + */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); - /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, - sizeof(struct ieee80211_supported_band)); + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; - } else { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), - &rtl_band_2ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - } else if (rtlhal->current_bandtype == BAND_ON_5G) { - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), - &rtl_band_5ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - ("Err BAND %d\n", - rtlhal->current_bandtype)); - } - } /* <5> set hw caps */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_BEACON_FILTER | - IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/ + /*IEEE80211_HW_SUPPORTS_PS | */ + /*IEEE80211_HW_PS_NULLFUNC_STACK | */ + /*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; - /* swlps or hwlps has been set in diff chip in init_sw_vars */ - if (rtlpriv->psc.swctrl_lps) - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - /* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ - 0; - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->rts_threshold = 2347; @@ -331,10 +199,9 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) /* TODO: Correct this value for our hw */ /* TODO: define these hard code value */ hw->channel_change_time = 100; - hw->max_listen_interval = 10; + hw->max_listen_interval = 5; hw->max_rate_tries = 4; /* hw->max_rates = 1; */ - hw->sta_data_size = sizeof(struct rtl_sta_info); /* <6> mac address */ if (is_valid_ether_addr(rtlefuse->dev_addr)) { @@ -363,10 +230,6 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, (void *)rtl_ips_nic_off_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.ps_work, - (void *)rtl_swlps_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, - (void *)rtl_swlps_rfon_wq_callback); } @@ -378,8 +241,6 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) cancel_delayed_work(&rtlpriv->works.watchdog_wq); cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); - cancel_delayed_work(&rtlpriv->works.ps_work); - cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); } void rtl_init_rfkill(struct ieee80211_hw *hw) @@ -390,16 +251,14 @@ void rtl_init_rfkill(struct ieee80211_hw *hw) bool blocked; u8 valid = 0; - /*set init state to on */ - rtlpriv->rfkill.rfkill_state = 1; - wiphy_rfkill_set_hw_state(hw->wiphy, 0); - radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); - if (valid) { - printk(KERN_INFO "rtlwifi: wireless switch is %s\n", - rtlpriv->rfkill.rfkill_state ? "on" : "off"); + /*set init state to that of switch */ + rtlpriv->rfkill.rfkill_state = radio_state; + printk(KERN_INFO "rtlwifi: wireless switch is %s\n", + rtlpriv->rfkill.rfkill_state ? "on" : "off"); + if (valid) { rtlpriv->rfkill.rfkill_state = radio_state; blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; @@ -449,8 +308,6 @@ int rtl_init_core(struct ieee80211_hw *hw) spin_lock_init(&rtlpriv->locks.rf_ps_lock); spin_lock_init(&rtlpriv->locks.rf_lock); spin_lock_init(&rtlpriv->locks.lps_lock); - spin_lock_init(&rtlpriv->locks.waitq_lock); - spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); rtlmac->link_state = MAC80211_NOLINK; @@ -470,6 +327,12 @@ void rtl_init_rx_config(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MGT_FILTER, + (u8 *) (&mac->rx_mgt_filter)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CTRL_FILTER, + (u8 *) (&mac->rx_ctrl_filter)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_DATA_FILTER, + (u8 *) (&mac->rx_data_filter)); } /********************************************************* @@ -496,40 +359,28 @@ static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, } static void _rtl_query_shortgi(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc, struct ieee80211_tx_info *info) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u8 rate_flag = info->control.rates[0].flags; - u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; - tcb_desc->use_shortgi = false; - if (sta == NULL) - return; - - sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; - sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + tcb_desc->use_shortgi = false; - if (!(sta->ht_cap.ht_supported)) + if (!mac->ht_enable) return; - if (!sgi_40 && !sgi_20) + if (!mac->sgi_40 && !mac->sgi_20) return; - if (mac->opmode == NL80211_IFTYPE_STATION) - bw_40 = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; - - if ((bw_40 == true) && sgi_40) + if ((mac->bw_40 == true) && mac->sgi_40) tcb_desc->use_shortgi = true; - else if ((bw_40 == false) && sgi_20) + else if ((mac->bw_40 == false) && mac->sgi_20) tcb_desc->use_shortgi = true; if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) tcb_desc->use_shortgi = false; + } static void _rtl_query_protection_mode(struct ieee80211_hw *hw, @@ -557,25 +408,19 @@ static void _rtl_query_protection_mode(struct ieee80211_hw *hw, tcb_desc->rts_enable = true; tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; } + } static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u8 ratr_index = 7; - if (sta) { - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - ratr_index = sta_entry->ratr_index; - } if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { - if (mac->opmode == NL80211_IFTYPE_STATION) { + if (mac->opmode == NL80211_IFTYPE_STATION) tcb_desc->ratr_index = 0; - } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { + else if (mac->opmode == NL80211_IFTYPE_ADHOC) { if (tcb_desc->multicast || tcb_desc->broadcast) { tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; @@ -583,61 +428,36 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, } else { /* TODO */ } - tcb_desc->ratr_index = ratr_index; - } else if (mac->opmode == NL80211_IFTYPE_AP) { - tcb_desc->ratr_index = ratr_index; } } if (rtlpriv->dm.useramask) { /* TODO we will differentiate adhoc and station futrue */ - if (mac->opmode == NL80211_IFTYPE_STATION) { - tcb_desc->mac_id = 0; - - if (mac->mode == WIRELESS_MODE_N_24G) - tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; - else if (mac->mode == WIRELESS_MODE_N_5G) - tcb_desc->ratr_index = RATR_INX_WIRELESS_NG; - else if (mac->mode & WIRELESS_MODE_G) - tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; - else if (mac->mode & WIRELESS_MODE_B) - tcb_desc->ratr_index = RATR_INX_WIRELESS_B; - else if (mac->mode & WIRELESS_MODE_A) - tcb_desc->ratr_index = RATR_INX_WIRELESS_G; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (NULL != sta) { - if (sta->aid > 0) - tcb_desc->mac_id = sta->aid + 1; - else - tcb_desc->mac_id = 1; - } else { - tcb_desc->mac_id = 0; - } + tcb_desc->mac_id = 0; + + if ((mac->mode == WIRELESS_MODE_N_24G) || + (mac->mode == WIRELESS_MODE_N_5G)) { + tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; + } else if (mac->mode & WIRELESS_MODE_G) { + tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; + } else if (mac->mode & WIRELESS_MODE_B) { + tcb_desc->ratr_index = RATR_INX_WIRELESS_B; } } } static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); tcb_desc->packet_bw = false; - if (!sta) + + if (!mac->bw_40 || !mac->ht_enable) return; - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (!(sta->ht_cap.ht_supported) || - !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - return; - } else if (mac->opmode == NL80211_IFTYPE_STATION) { - if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) - return; - } + if (tcb_desc->multicast || tcb_desc->broadcast) return; @@ -664,21 +484,22 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw) void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct ieee80211_rate *txrate; __le16 fc = hdr->frame_control; - txrate = ieee80211_get_tx_rate(hw, info); - tcb_desc->hw_rate = txrate->hw_value; + memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (ieee80211_is_data(fc)) { + txrate = ieee80211_get_tx_rate(hw, info); + tcb_desc->hw_rate = txrate->hw_value; + /* - *we set data rate INX 0 + *we set data rate RTL_RC_CCK_RATE1M *in rtl_rc.c if skb is special data or *mgt which need low data rate. */ @@ -687,11 +508,12 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *So tcb_desc->hw_rate is just used for *special data and mgt frames */ - if (info->control.rates[0].idx == 0 && - ieee80211_is_nullfunc(fc)) { + if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) { tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; + tcb_desc->ratr_index = 7; + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; tcb_desc->disable_ratefallback = 1; } else { /* @@ -701,7 +523,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, *and N rate will all be controled by FW *when tcb_desc->use_driver_rate = false */ - if (sta && (sta->ht_cap.ht_supported)) { + if (rtlmac->ht_enable) { tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); } else { if (rtlmac->mode == WIRELESS_MODE_B) { @@ -719,25 +541,43 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tcb_desc->broadcast = 1; - _rtl_txrate_selectmode(hw, sta, tcb_desc); - _rtl_query_bandwidth_mode(hw, sta, tcb_desc); + _rtl_txrate_selectmode(hw, tcb_desc); + _rtl_query_bandwidth_mode(hw, tcb_desc); _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); - _rtl_query_shortgi(hw, sta, tcb_desc, info); + _rtl_query_shortgi(hw, tcb_desc, info); _rtl_query_protection_mode(hw, tcb_desc, info); } else { tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; + tcb_desc->ratr_index = 7; tcb_desc->disable_ratefallback = 1; tcb_desc->mac_id = 0; - tcb_desc->packet_bw = false; + + tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; } } EXPORT_SYMBOL(rtl_get_tcb_desc); +bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); + rtl_ips_nic_on(hw); + + mac->link_state = MAC80211_LINKING; + } + + return true; +} + bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct rtl_priv *rtlpriv = rtl_priv(hw); __le16 fc = hdr->frame_control; u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN)); @@ -782,20 +622,22 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - __le16 fc = rtl_get_fc(skb); + __le16 fc = hdr->frame_control; u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; if (!ieee80211_is_data(fc)) - return false; + goto end; + if (ieee80211_is_nullfunc(fc)) + return true; ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); - /* ether_type = ntohs(ether_type); */ if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { @@ -844,6 +686,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) return true; } +end: return false; } @@ -852,92 +695,61 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) * functions called by core.c * *********************************************************/ -int rtl_tx_agg_start(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) +int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_tid_data *tid_data; struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - if (sta == NULL) - return -EINVAL; + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("on ra = %pM tid = %d\n", ra, tid)); if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - if (!sta_entry) + if (mac->tids[tid].agg.agg_state != RTL_AGG_OFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Start AGG when state is not RTL_AGG_OFF !\n")); return -ENXIO; - tid_data = &sta_entry->tids[tid]; + } - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("on ra = %pM tid = %d seq:%d\n", sta->addr, tid, - tid_data->seq_number)); + tid_data = &mac->tids[tid]; + *ssn = SEQ_TO_SN(tid_data->seq_number); - *ssn = tid_data->seq_number; - tid_data->agg.agg_state = RTL_AGG_START; + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + ("HW queue is empty tid:%d\n", tid)); + tid_data->agg.agg_state = RTL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); + ieee80211_start_tx_ba_cb_irqsafe(mac->vif, ra, tid); return 0; } -int rtl_tx_agg_stop(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid) +int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 * ra, u16 tid) { + int ssn = -1; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_tid_data *tid_data; - struct rtl_sta_info *sta_entry = NULL; - - if (sta == NULL) - return -EINVAL; - if (!sta->addr) { + if (!ra) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); return -EINVAL; } - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("on ra = %pM tid = %d\n", sta->addr, tid)); - if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - tid_data = &sta_entry->tids[tid]; - sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; - - ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); + if (mac->tids[tid].agg.agg_state != RTL_AGG_ON) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Stopping AGG while state not ON or starting\n")); - return 0; -} + tid_data = &mac->tids[tid]; + ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; -int rtl_tx_agg_oper(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_tid_data *tid_data; - struct rtl_sta_info *sta_entry = NULL; + mac->tids[tid].agg.agg_state = RTL_AGG_OFF; - if (sta == NULL) - return -EINVAL; - - if (!sta->addr) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); - return -EINVAL; - } - - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - ("on ra = %pM tid = %d\n", sta->addr, tid)); - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - tid_data = &sta_entry->tids[tid]; - sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; + ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, ra, tid); return 0; } @@ -956,16 +768,18 @@ void rtl_watchdog_wq_callback(void *data) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + bool busytraffic = false; bool higher_busytraffic = false; bool higher_busyrxtraffic = false; - u8 idx, tid; + bool higher_busytxtraffic = false; + + u8 idx = 0; u32 rx_cnt_inp4eriod = 0; u32 tx_cnt_inp4eriod = 0; u32 aver_rx_cnt_inperiod = 0; u32 aver_tx_cnt_inperiod = 0; - u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; - u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; + bool enter_ps = false; if (is_hal_stop(rtlhal)) @@ -979,6 +793,9 @@ void rtl_watchdog_wq_callback(void *data) mac->cnt_after_linked = 0; } + /* <2> DM */ + rtlpriv->cfg->ops->dm_watchdog(hw); + /* *<3> to check if traffic busy, if * busytraffic we don't change channel @@ -1017,27 +834,8 @@ void rtl_watchdog_wq_callback(void *data) /* Extremely high Rx data. */ if (aver_rx_cnt_inperiod > 5000) higher_busyrxtraffic = true; - } - - /* check every tid's tx traffic */ - for (tid = 0; tid <= 7; tid++) { - for (idx = 0; idx <= 2; idx++) - rtlpriv->link_info.tidtx_in4period[tid][idx] = - rtlpriv->link_info.tidtx_in4period[tid] - [idx + 1]; - rtlpriv->link_info.tidtx_in4period[tid][3] = - rtlpriv->link_info.tidtx_inperiod[tid]; - - for (idx = 0; idx <= 3; idx++) - tidtx_inp4eriod[tid] += - rtlpriv->link_info.tidtx_in4period[tid][idx]; - aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; - if (aver_tidtx_inperiod[tid] > 5000) - rtlpriv->link_info.higher_busytxtraffic[tid] = - true; else - rtlpriv->link_info.higher_busytxtraffic[tid] = - false; + higher_busytxtraffic = false; } if (((rtlpriv->link_info.num_rx_inperiod + @@ -1056,15 +854,11 @@ void rtl_watchdog_wq_callback(void *data) rtlpriv->link_info.num_rx_inperiod = 0; rtlpriv->link_info.num_tx_inperiod = 0; - for (tid = 0; tid <= 7; tid++) - rtlpriv->link_info.tidtx_inperiod[tid] = 0; rtlpriv->link_info.busytraffic = busytraffic; rtlpriv->link_info.higher_busytraffic = higher_busytraffic; rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; - /* <3> DM */ - rtlpriv->cfg->ops->dm_watchdog(hw); } void rtl_watch_dog_timer_callback(unsigned long data) @@ -1079,268 +873,6 @@ void rtl_watch_dog_timer_callback(unsigned long data) jiffies + MSECS(RTL_WATCH_DOG_TIME)); } -/********************************************************* - * - * frame process functions - * - *********************************************************/ -u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) -{ - struct ieee80211_mgmt *mgmt = (void *)data; - u8 *pos, *end; - - pos = (u8 *)mgmt->u.beacon.variable; - end = data + len; - while (pos < end) { - if (pos + 2 + pos[1] > end) - return NULL; - - if (pos[0] == ie) - return pos; - - pos += 2 + pos[1]; - } - return NULL; -} - -/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ -/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ -static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, - enum ieee80211_smps_mode smps, u8 *da, u8 *bssid) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct sk_buff *skb; - struct ieee80211_mgmt *action_frame; - - /* 27 = header + category + action + smps mode */ - skb = dev_alloc_skb(27 + hw->extra_tx_headroom); - if (!skb) - return NULL; - - skb_reserve(skb, hw->extra_tx_headroom); - action_frame = (void *)skb_put(skb, 27); - memset(action_frame, 0, 27); - memcpy(action_frame->da, da, ETH_ALEN); - memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); - memcpy(action_frame->bssid, bssid, ETH_ALEN); - action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - action_frame->u.action.category = WLAN_CATEGORY_HT; - action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; - switch (smps) { - case IEEE80211_SMPS_AUTOMATIC:/* 0 */ - case IEEE80211_SMPS_NUM_MODES:/* 4 */ - WARN_ON(1); - case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ - action_frame->u.action.u.ht_smps.smps_control = - WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ - break; - case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ - action_frame->u.action.u.ht_smps.smps_control = - WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ - break; - case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ - action_frame->u.action.u.ht_smps.smps_control = - WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ - break; - } - - return skb; -} - -int rtl_send_smps_action(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 *da, u8 *bssid, - enum ieee80211_smps_mode smps) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); - struct rtl_tcb_desc tcb_desc; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - - if (rtlpriv->mac80211.act_scanning) - goto err_free; - - if (!sta) - goto err_free; - - if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) - goto err_free; - - if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) - goto err_free; - - /* this is a type = mgmt * stype = action frame */ - if (skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl_sta_info *sta_entry = - (struct rtl_sta_info *) sta->drv_priv; - sta_entry->mimo_ps = smps; - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); - - info->control.rates[0].idx = 0; - info->control.sta = sta; - info->band = hw->conf.channel->band; - rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); - } -err_free: - return 0; -} - -/********************************************************* - * - * IOT functions - * - *********************************************************/ -static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, - struct octet_string vendor_ie) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool matched = false; - static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; - static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; - static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; - static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; - static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; - static u8 racap[] = { 0x00, 0x0c, 0x43 }; - static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; - static u8 marvcap[] = { 0x00, 0x50, 0x43 }; - - if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || - memcmp(vendor_ie.octet, athcap_2, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_ATH; - matched = true; - } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || - memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || - memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_BROAD; - matched = true; - } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_RAL; - matched = true; - } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_CISCO; - matched = true; - } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_MARV; - matched = true; - } - - return matched; -} - -static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, - unsigned int len) -{ - struct ieee80211_mgmt *mgmt = (void *)data; - struct octet_string vendor_ie; - u8 *pos, *end; - - pos = (u8 *)mgmt->u.beacon.variable; - end = data + len; - while (pos < end) { - if (pos[0] == 221) { - vendor_ie.length = pos[1]; - vendor_ie.octet = &pos[2]; - if (rtl_chk_vendor_ouisub(hw, vendor_ie)) - return true; - } - - if (pos + 2 + pos[1] > end) - return false; - - pos += 2 + pos[1]; - } - return false; -} - -void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (void *)data; - u32 vendor = PEER_UNKNOWN; - - static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; - static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; - static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; - static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; - static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; - static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; - static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; - static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; - static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; - static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; - static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; - static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; - static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; - static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; - static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; - static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; - - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - - if (mac->link_state == MAC80211_NOLINK) { - mac->vendor = PEER_UNKNOWN; - return; - } - - if (mac->cnt_after_linked > 2) - return; - - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - - /* min. beacon length + FCS_LEN */ - if (len <= 40 + FCS_LEN) - return; - - /* and only beacons from the associated BSSID, please */ - if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) - return; - - if (rtl_find_221_ie(hw, data, len)) - vendor = mac->vendor; - - if ((memcmp(mac->bssid, ap5_1, 3) == 0) || - (memcmp(mac->bssid, ap5_2, 3) == 0) || - (memcmp(mac->bssid, ap5_3, 3) == 0) || - (memcmp(mac->bssid, ap5_4, 3) == 0) || - (memcmp(mac->bssid, ap5_5, 3) == 0) || - (memcmp(mac->bssid, ap5_6, 3) == 0) || - vendor == PEER_ATH) { - vendor = PEER_ATH; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ath find\n")); - } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || - (memcmp(mac->bssid, ap4_5, 3) == 0) || - (memcmp(mac->bssid, ap4_1, 3) == 0) || - (memcmp(mac->bssid, ap4_2, 3) == 0) || - (memcmp(mac->bssid, ap4_3, 3) == 0) || - vendor == PEER_RAL) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ral findn\n")); - vendor = PEER_RAL; - } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || - vendor == PEER_CISCO) { - vendor = PEER_CISCO; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>cisco find\n")); - } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || - (memcmp(mac->bssid, ap3_2, 3) == 0) || - (memcmp(mac->bssid, ap3_3, 3) == 0) || - vendor == PEER_BROAD) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>broad find\n")); - vendor = PEER_BROAD; - } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || - vendor == PEER_MARV) { - vendor = PEER_MARV; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>marv find\n")); - } - - mac->vendor = vendor; -} - /********************************************************* * * sysfs functions @@ -1408,13 +940,12 @@ static int __init rtl_core_module_init(void) if (rtl_rate_control_register()) printk(KERN_ERR "rtlwifi: Unable to register rtl_rc," "use default RC !!\n"); - return 0; } static void __exit rtl_core_module_exit(void) { - /*RC*/ + /*RC*/ rtl_rate_control_unregister(); } diff --git a/trunk/drivers/net/wireless/rtlwifi/base.h b/trunk/drivers/net/wireless/rtlwifi/base.h index a91f3eee59c8..043045342bc7 100644 --- a/trunk/drivers/net/wireless/rtlwifi/base.h +++ b/trunk/drivers/net/wireless/rtlwifi/base.h @@ -24,26 +24,13 @@ * Hsinchu 300, Taiwan. * * Larry Finger - * *****************************************************************************/ #ifndef __RTL_BASE_H__ #define __RTL_BASE_H__ -enum ap_peer { - PEER_UNKNOWN = 0, - PEER_RTL = 1, - PEER_RTL_92SE = 2, - PEER_BROAD = 3, - PEER_RAL = 4, - PEER_ATH = 5, - PEER_CISCO = 6, - PEER_MARV = 7, - PEER_AIRGO = 9, - PEER_MAX = 10, -} ; - #define RTL_DUMMY_OFFSET 0 +#define RTL_RX_DESC_SIZE 24 #define RTL_DUMMY_UNIT 8 #define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) #define RTL_TX_DESC_SIZE 32 @@ -66,14 +53,6 @@ enum ap_peer { #define FRAME_OFFSET_SEQUENCE 22 #define FRAME_OFFSET_ADDRESS4 24 -#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ - WRITEEF2BYTE(_hdr, _val) -#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ - WRITEEF1BYTE(_hdr, _val) -#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ - SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) -#define SET_80211_HDR_TO_DS(_hdr, _val) \ - SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) #define SET_80211_PS_POLL_AID(_hdr, _val) \ (*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val)) @@ -85,27 +64,11 @@ enum ap_peer { #define SET_80211_HDR_DURATION(_hdr, _val) \ (*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val)) #define SET_80211_HDR_ADDRESS1(_hdr, _val) \ - CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8 *)(_val)) + memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val), ETH_ALEN) #define SET_80211_HDR_ADDRESS2(_hdr, _val) \ - CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) + memcpy((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val), ETH_ALEN) #define SET_80211_HDR_ADDRESS3(_hdr, _val) \ - CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) -#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ - WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) - -#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ - WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) -#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ - WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) -#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ - WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) -#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ - READEF2BYTE(((u8 *)(__phdr)) + 34) -#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ - WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) -#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ - SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ - (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) + memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val), ETH_ALEN) int rtl_init_core(struct ieee80211_hw *hw); void rtl_deinit_core(struct ieee80211_hw *hw); @@ -117,27 +80,18 @@ void rtl_watch_dog_timer_callback(unsigned long data); void rtl_deinit_deferred_work(struct ieee80211_hw *hw); bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); +bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); void rtl_watch_dog_timer_callback(unsigned long data); -int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, +int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn); -int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - u16 tid); -int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - u16 tid); +int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid); void rtl_watchdog_wq_callback(void *data); void rtl_get_tcb_desc(struct ieee80211_hw *hw, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); -int rtl_send_smps_action(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 *da, u8 *bssid, - enum ieee80211_smps_mode smps); -u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); -void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); -u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid); extern struct attribute_group rtl_attribute_group; #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/cam.c b/trunk/drivers/net/wireless/rtlwifi/cam.c index 7295af0536b7..52c9c1367cac 100644 --- a/trunk/drivers/net/wireless/rtlwifi/cam.c +++ b/trunk/drivers/net/wireless/rtlwifi/cam.c @@ -23,8 +23,6 @@ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * - * Larry Finger - * *****************************************************************************/ #include "wifi.h" @@ -51,7 +49,7 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, u32 target_content = 0; u8 entry_i; - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("key_cont_128:\n %x:%x:%x:%x:%x:%x\n", key_cont_128[0], key_cont_128[1], key_cont_128[2], key_cont_128[3], @@ -70,13 +68,15 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], target_command); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("WRITE %x: %x\n", + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): " + "WRITE %x: %x\n", rtlpriv->cfg->maps[WCAMI], target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("The Key ID is %d\n", entry_no)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("WRITE %x: %x\n", + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): " + "WRITE %x: %x\n", rtlpriv->cfg->maps[RWCAM], target_command)); } else if (entry_i == 1) { @@ -91,10 +91,12 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], target_command); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("WRITE A4: %x\n", target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("WRITE A0: %x\n", target_command)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A4: %x\n", + target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A0: %x\n", + target_command)); } else { @@ -111,14 +113,16 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, target_command); udelay(100); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("WRITE A4: %x\n", target_content)); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("WRITE A0: %x\n", target_command)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A4: %x\n", + target_content)); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + ("rtl_cam_program_entry(): WRITE A0: %x\n", + target_command)); } } - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("after set key, usconfig:%x\n", us_config)); } @@ -285,71 +289,3 @@ void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) } EXPORT_SYMBOL(rtl_cam_empty_entry); - -u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; - u8 entry_idx = 0; - u8 i, *addr; - - if (NULL == sta_addr) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - ("sta_addr is NULL.\n")); - return TOTAL_CAM_ENTRY; - } - /* Does STA already exist? */ - for (i = 4; i < TOTAL_CAM_ENTRY; i++) { - addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; - if (memcmp(addr, sta_addr, ETH_ALEN) == 0) - return i; - } - /* Get a free CAM entry. */ - for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { - if ((bitmap & BIT(0)) == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - ("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", - rtlpriv->sec.hwsec_cam_bitmap, entry_idx)); - rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; - memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], - sta_addr, ETH_ALEN); - return entry_idx; - } - bitmap = bitmap >> 1; - } - return TOTAL_CAM_ENTRY; -} -EXPORT_SYMBOL(rtl_cam_get_free_entry); - -void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 bitmap; - u8 i, *addr; - - if (NULL == sta_addr) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - ("sta_addr is NULL.\n")); - } - - if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\ - sta_addr[4]|sta_addr[5]) == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - ("sta_addr is 00:00:00:00:00:00.\n")); - return; - } - /* Does STA already exist? */ - for (i = 4; i < TOTAL_CAM_ENTRY; i++) { - addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; - bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; - if (((bitmap & BIT(0)) == BIT(0)) && - (memcmp(addr, sta_addr, ETH_ALEN) == 0)) { - /* Remove from HW Security CAM */ - memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); - rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); - printk(KERN_INFO "&&&&&&&&&del entry %d\n", i); - } - } - return; -} -EXPORT_SYMBOL(rtl_cam_del_entry); diff --git a/trunk/drivers/net/wireless/rtlwifi/cam.h b/trunk/drivers/net/wireless/rtlwifi/cam.h index c62da4eefc75..dd82f057d53d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/cam.h +++ b/trunk/drivers/net/wireless/rtlwifi/cam.h @@ -23,13 +23,12 @@ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * - * Larry Finger - * *****************************************************************************/ #ifndef __RTL_CAM_H_ #define __RTL_CAM_H_ +#define TOTAL_CAM_ENTRY 32 #define CAM_CONTENT_COUNT 8 #define CFG_DEFAULT_KEY BIT(5) @@ -50,7 +49,5 @@ int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); -u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr); -void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/core.c b/trunk/drivers/net/wireless/rtlwifi/core.c index fc89cd8c8320..e4f4aee8f298 100644 --- a/trunk/drivers/net/wireless/rtlwifi/core.c +++ b/trunk/drivers/net/wireless/rtlwifi/core.c @@ -24,7 +24,6 @@ * Hsinchu 300, Taiwan. * * Larry Finger - * *****************************************************************************/ #include "wifi.h" @@ -36,7 +35,7 @@ /*mutex for start & stop is must here. */ static int rtl_op_start(struct ieee80211_hw *hw) { - int err; + int err = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -46,8 +45,10 @@ static int rtl_op_start(struct ieee80211_hw *hw) return 0; mutex_lock(&rtlpriv->locks.conf_mutex); err = rtlpriv->intf_ops->adapter_start(hw); - if (!err) - rtl_watch_dog_timer_callback((unsigned long)hw); + if (err) + goto out; + rtl_watch_dog_timer_callback((unsigned long)hw); +out: mutex_unlock(&rtlpriv->locks.conf_mutex); return err; } @@ -71,7 +72,6 @@ static void rtl_op_stop(struct ieee80211_hw *hw) mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); - mac->vendor = PEER_UNKNOWN; /*reset sec info */ rtl_cam_reset_sec_info(hw); @@ -87,8 +87,6 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_tcb_desc tcb_desc; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) goto err_free; @@ -96,8 +94,8 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) goto err_free; - if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) - rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); + + rtlpriv->intf_ops->adapter_tx(hw, skb); return; @@ -138,26 +136,10 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, mac->link_state = MAC80211_LINKED; rtlpriv->cfg->ops->set_bcn_reg(hw); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - mac->basic_rates = 0xfff; - else - mac->basic_rates = 0xff0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *) (&mac->basic_rates)); - break; case NL80211_IFTYPE_AP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("NL80211_IFTYPE_AP\n")); - - mac->link_state = MAC80211_LINKED; - rtlpriv->cfg->ops->set_bcn_reg(hw); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - mac->basic_rates = 0xfff; - else - mac->basic_rates = 0xff0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *) (&mac->basic_rates)); break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -204,12 +186,13 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, mac->vif = NULL; mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); - mac->vendor = PEER_UNKNOWN; mac->opmode = NL80211_IFTYPE_UNSPECIFIED; rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + mutex_unlock(&rtlpriv->locks.conf_mutex); } + static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -241,25 +224,10 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /*For LPS */ if (changed & IEEE80211_CONF_CHANGE_PS) { - cancel_delayed_work(&rtlpriv->works.ps_work); - cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); - if (conf->flags & IEEE80211_CONF_PS) { - rtlpriv->psc.sw_ps_enabled = true; - /* sleep here is must, or we may recv the beacon and - * cause mac80211 into wrong ps state, this will cause - * power save nullfunc send fail, and further cause - * pkt loss, So sleep must quickly but not immediatly - * because that will cause nullfunc send by mac80211 - * fail, and cause pkt loss, we have tested that 5mA - * is worked very well */ - if (!rtlpriv->psc.multi_buffered) - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.ps_work, - MSECS(5)); - } else { - rtl_swlps_rf_awake(hw); - rtlpriv->psc.sw_ps_enabled = false; - } + if (conf->flags & IEEE80211_CONF_PS) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); } if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { @@ -291,7 +259,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) case NL80211_CHAN_NO_HT: /* SC */ mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_DONT_CARE; + PRIME_CHNL_OFFSET_DONT_CARE; rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; mac->bw_40 = false; break; @@ -299,7 +267,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; + HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ @@ -310,7 +278,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) /* SC */ mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; + HT_CHANNEL_WIDTH_20_40; mac->bw_40 = true; /*wide channel */ @@ -320,29 +288,16 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) default: mac->bw_40 = false; RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("switch case not processed\n")); + ("switch case not processed\n")); break; } if (wide_chan <= 0) wide_chan = 1; - - /* In scanning, before we go offchannel we may send a ps=1 null - * to AP, and then we may send a ps = 0 null to AP quickly, but - * first null may have caused AP to put lots of packet to hw tx - * buffer. These packets must be tx'd before we go off channel - * so we must delay more time to let AP flush these packets - * before going offchannel, or dis-association or delete BA will - * happen by AP - */ - if (rtlpriv->mac80211.offchan_deley) { - rtlpriv->mac80211.offchan_deley = false; - mdelay(50); - } rtlphy->current_channel = wide_chan; - rtlpriv->cfg->ops->switch_channel(hw); rtlpriv->cfg->ops->set_channel_access(hw); + rtlpriv->cfg->ops->switch_channel(hw); rtlpriv->cfg->ops->set_bw_mode(hw, hw->conf.channel_type); } @@ -390,28 +345,27 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, } } - /* if ssid not set to hw don't check bssid - * here just used for linked scanning, & linked - * and nolink check bssid is set in set network_type */ - if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && - (mac->link_state >= MAC80211_LINKED)) { - if (mac->opmode != NL80211_IFTYPE_AP) { - if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { - rtlpriv->cfg->ops->set_chk_bssid(hw, false); - } else { - rtlpriv->cfg->ops->set_chk_bssid(hw, true); - } - } + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + /* + *TODO: BIT(5) is probe response BIT(8) is beacon + *TODO: Use define for BIT(5) and BIT(8) + */ + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) + mac->rx_mgt_filter |= (BIT(5) | BIT(8)); + else + mac->rx_mgt_filter &= ~(BIT(5) | BIT(8)); } if (changed_flags & FIF_CONTROL) { if (*new_flags & FIF_CONTROL) { mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; + mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("Enable receive control frame.\n")); } else { mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; + mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("Disable receive control frame.\n")); } @@ -428,54 +382,14 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, ("Disable receive other BSS's frame.\n")); } } -} -static int rtl_op_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry; - - if (sta) { - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - sta_entry->wireless_mode = WIRELESS_MODE_G; - if (sta->supp_rates[0] <= 0xf) - sta_entry->wireless_mode = WIRELESS_MODE_B; - if (sta->ht_cap.ht_supported == true) - sta_entry->wireless_mode = WIRELESS_MODE_N_24G; - } else if (rtlhal->current_bandtype == BAND_ON_5G) { - sta_entry->wireless_mode = WIRELESS_MODE_A; - if (sta->ht_cap.ht_supported == true) - sta_entry->wireless_mode = WIRELESS_MODE_N_24G; - } - - /* I found some times mac80211 give wrong supp_rates for adhoc*/ - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) - sta_entry->wireless_mode = WIRELESS_MODE_G; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); - } - return 0; -} -static int rtl_op_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry; - if (sta) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - sta_entry->wireless_mode = 0; - sta_entry->ratr_index = 0; - } - return 0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, + (u8 *) (&mac->rx_mgt_filter)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, + (u8 *) (&mac->rx_ctrl_filter)); } + static int _rtl_get_hal_qnum(u16 queue) { int qnum; @@ -532,18 +446,19 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct ieee80211_sta *sta = NULL; mutex_lock(&rtlpriv->locks.conf_mutex); + if ((vif->type == NL80211_IFTYPE_ADHOC) || (vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_MESH_POINT)) { + if ((changed & BSS_CHANGED_BEACON) || (changed & BSS_CHANGED_BEACON_ENABLED && bss_conf->enable_beacon)) { + if (mac->beacon_enabled == 0) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_BEACON_ENABLED\n")); @@ -555,13 +470,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, rtlpriv->cfg->maps [RTL_IBSS_INT_MASKS], 0); - - if (rtlpriv->cfg->ops->linked_set_reg) - rtlpriv->cfg->ops->linked_set_reg(hw); } - } - if ((changed & BSS_CHANGED_BEACON_ENABLED && - !bss_conf->enable_beacon)) { + } else { if (mac->beacon_enabled == 1) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("ADHOC DISABLE BEACON\n")); @@ -572,6 +482,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, [RTL_IBSS_INT_MASKS]); } } + if (changed & BSS_CHANGED_BEACON_INT) { RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, ("BSS_CHANGED_BEACON_INT\n")); @@ -583,25 +494,11 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, /*TODO: reference to enum ieee80211_bss_change */ if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { - /* we should reset all sec info & cam - * before set cam after linked, we should not - * reset in disassoc, that will cause tkip->wep - * fail because some flag will be wrong */ - /* reset sec info */ - rtl_cam_reset_sec_info(hw); - /* reset cam to fix wep fail issue - * when change from wpa to wep */ - rtl_cam_reset_all_entry(hw); - mac->link_state = MAC80211_LINKED; mac->cnt_after_linked = 0; mac->assoc_id = bss_conf->aid; memcpy(mac->bssid, bss_conf->bssid, 6); - if (rtlpriv->cfg->ops->linked_set_reg) - rtlpriv->cfg->ops->linked_set_reg(hw); - if (mac->opmode == NL80211_IFTYPE_STATION && sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_ASSOC\n")); } else { @@ -610,7 +507,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); - mac->vendor = PEER_UNKNOWN; + + /* reset sec info */ + rtl_cam_reset_sec_info(hw); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, ("BSS_CHANGED_UN_ASSOC\n")); @@ -647,10 +546,14 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { + struct ieee80211_sta *sta = NULL; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("BSS_CHANGED_HT\n")); + rcu_read_lock(); - sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); + sta = ieee80211_find_sta(mac->vif, mac->bssid); + if (sta) { if (sta->ht_cap.ampdu_density > mac->current_ampdu_density) @@ -672,7 +575,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BSSID) { + struct ieee80211_sta *sta = NULL; u32 basic_rates; + u8 i; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, (u8 *) bss_conf->bssid); @@ -680,65 +585,96 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); - mac->vendor = PEER_UNKNOWN; memcpy(mac->bssid, bss_conf->bssid, 6); - rtlpriv->cfg->ops->set_network_type(hw, vif->type); + if (is_valid_ether_addr(bss_conf->bssid)) { + switch (vif->type) { + case NL80211_IFTYPE_UNSPECIFIED: + break; + case NL80211_IFTYPE_ADHOC: + break; + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_AP: + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("switch case not process\n")); + break; + } + rtlpriv->cfg->ops->set_network_type(hw, vif->type); + } else + rtlpriv->cfg->ops->set_network_type(hw, + NL80211_IFTYPE_UNSPECIFIED); + + memset(mac->mcs, 0, 16); + mac->ht_enable = false; + mac->sgi_40 = false; + mac->sgi_20 = false; + + if (!bss_conf->use_short_slot) + mac->mode = WIRELESS_MODE_B; + else + mac->mode = WIRELESS_MODE_G; rcu_read_lock(); - sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); - if (!sta) { - rcu_read_unlock(); - goto out; - } - - if (rtlhal->current_bandtype == BAND_ON_5G) { - mac->mode = WIRELESS_MODE_A; - } else { - if (sta->supp_rates[0] <= 0xf) - mac->mode = WIRELESS_MODE_B; - else - mac->mode = WIRELESS_MODE_G; - } + sta = ieee80211_find_sta(mac->vif, mac->bssid); - if (sta->ht_cap.ht_supported) { - if (rtlhal->current_bandtype == BAND_ON_2_4G) + if (sta) { + if (sta->ht_cap.ht_supported) { mac->mode = WIRELESS_MODE_N_24G; - else - mac->mode = WIRELESS_MODE_N_5G; - } - - /* just station need it, because ibss & ap mode will - * set in sta_add, and will be NULL here */ - if (mac->opmode == NL80211_IFTYPE_STATION) { - struct rtl_sta_info *sta_entry; - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - sta_entry->wireless_mode = mac->mode; - } - - if (sta->ht_cap.ht_supported) { - mac->ht_enable = true; + mac->ht_enable = true; + } - /* - * for cisco 1252 bw20 it's wrong - * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - * mac->bw_40 = true; - * } - * */ + if (mac->ht_enable) { + u16 ht_cap = sta->ht_cap.cap; + memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16); + + for (i = 0; i < 16; i++) + RT_TRACE(rtlpriv, COMP_MAC80211, + DBG_LOUD, ("%x ", + mac->mcs[i])); + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + ("\n")); + + if (ht_cap & IEEE80211_HT_CAP_SGI_40) + mac->sgi_40 = true; + + if (ht_cap & IEEE80211_HT_CAP_SGI_20) + mac->sgi_20 = true; + + /* + * for cisco 1252 bw20 it's wrong + * if (ht_cap & + * IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + * mac->bw_40 = true; + * } + */ + } } + rcu_read_unlock(); + /*mac80211 just give us CCK rates any time + *So we add G rate in basic rates when + not in B mode*/ if (changed & BSS_CHANGED_BASIC_RATES) { - /* for 5G must << RATE_6M_INDEX=4, - * because 5G have no cck rate*/ - if (rtlhal->current_bandtype == BAND_ON_5G) - basic_rates = sta->supp_rates[1] << 4; + if (mac->mode == WIRELESS_MODE_B) + basic_rates = bss_conf->basic_rates | 0x00f; else - basic_rates = sta->supp_rates[0]; + basic_rates = bss_conf->basic_rates | 0xff0; + + if (!vif) + goto out; mac->basic_rates = basic_rates; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, (u8 *) (&basic_rates)); + + if (rtlpriv->dm.useramask) + rtlpriv->cfg->ops->update_rate_mask(hw, 0); + else + rtlpriv->cfg->ops->update_rate_table(hw); + } - rcu_read_unlock(); } /* @@ -824,17 +760,16 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_START: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid)); - return rtl_tx_agg_start(hw, sta, tid, ssn); + return rtl_tx_agg_start(hw, sta->addr, tid, ssn); break; case IEEE80211_AMPDU_TX_STOP: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid)); - return rtl_tx_agg_stop(hw, sta, tid); + return rtl_tx_agg_stop(hw, sta->addr, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid)); - rtl_tx_agg_oper(hw, sta, tid); break; case IEEE80211_AMPDU_RX_START: RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, @@ -864,12 +799,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) if (mac->link_state == MAC80211_LINKED) { rtl_lps_leave(hw); mac->link_state = MAC80211_LINKED_SCANNING; - } else { + } else rtl_ips_nic_on(hw); - } - - /* Dual mac */ - rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); @@ -881,19 +812,22 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); - mac->act_scanning = false; - /* Dual mac */ - rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); + mac->act_scanning = false; if (mac->link_state == MAC80211_LINKED_SCANNING) { mac->link_state = MAC80211_LINKED; - if (mac->opmode == NL80211_IFTYPE_STATION) { - /* fix fwlps issue */ - rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - } + + /* fix fwlps issue */ + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + + if (rtlpriv->dm.useramask) + rtlpriv->cfg->ops->update_rate_mask(hw, 0); + else + rtlpriv->cfg->ops->update_rate_table(hw); + } - rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); } static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -924,73 +858,49 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, rtl_ips_nic_on(hw); mutex_lock(&rtlpriv->locks.conf_mutex); /* <1> get encryption alg */ - switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: key_type = WEP40_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n")); + rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_WEP104: RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP104\n")); key_type = WEP104_ENCRYPTION; + rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_TKIP: key_type = TKIP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n")); + if (mac->opmode == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; break; case WLAN_CIPHER_SUITE_CCMP: key_type = AESCCMP_ENCRYPTION; RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n")); + if (mac->opmode == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("alg_err:%x!!!!:\n", key->cipher)); goto out_unlock; } - if (key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION || - mac->opmode == NL80211_IFTYPE_ADHOC) - rtlpriv->sec.use_defaultkey = true; - /* <2> get key_idx */ key_idx = (u8) (key->keyidx); if (key_idx > 3) goto out_unlock; /* <3> if pairwise key enable_hw_sec */ group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); - - /* wep always be group key, but there are two conditions: - * 1) wep only: is just for wep enc, in this condition - * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION - * will be true & enable_hw_sec will be set when wep - * ke setting. - * 2) wep(group) + AES(pairwise): some AP like cisco - * may use it, in this condition enable_hw_sec will not - * be set when wep key setting */ - /* we must reset sec_info after lingked before set key, - * or some flag will be wrong*/ - if (mac->opmode == NL80211_IFTYPE_AP) { - if (!group_key || key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION) { - if (group_key) - wep_only = true; - rtlpriv->cfg->ops->enable_hw_sec(hw); - } - } else { - if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || - rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { - if (rtlpriv->sec.pairwise_enc_algorithm == - NO_ENCRYPTION && - (key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION)) - wep_only = true; - rtlpriv->sec.pairwise_enc_algorithm = key_type; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1" - " TKIP:2 AES:4 WEP104:5)\n", key_type)); - rtlpriv->cfg->ops->enable_hw_sec(hw); - } + if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || + rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { + if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && + (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION)) + wep_only = true; + rtlpriv->sec.pairwise_enc_algorithm = key_type; + rtlpriv->cfg->ops->enable_hw_sec(hw); } /* <4> set key based on cmd */ switch (cmd) { @@ -1022,7 +932,6 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!sta) { RT_ASSERT(false, ("pairwise key withnot" "mac_addr\n")); - err = -EOPNOTSUPP; goto out_unlock; } @@ -1050,10 +959,6 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("disable key delete one entry\n")); /*set local buf about wep key. */ - if (mac->opmode == NL80211_IFTYPE_AP) { - if (sta) - rtl_cam_del_entry(hw, sta->addr); - } memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); rtlpriv->sec.key_len[key_idx] = 0; memcpy(mac_addr, zero_addr, ETH_ALEN); @@ -1106,18 +1011,6 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) mutex_unlock(&rtlpriv->locks.conf_mutex); } -/* this function is called by mac80211 to flush tx buffer - * before switch channle or power save, or tx buffer packet - * maybe send after offchannel or rf sleep, this may cause - * dis-association by AP */ -static void rtl_op_flush(struct ieee80211_hw *hw, bool drop) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->intf_ops->flush) - rtlpriv->intf_ops->flush(hw, drop); -} - const struct ieee80211_ops rtl_ops = { .start = rtl_op_start, .stop = rtl_op_stop, @@ -1126,8 +1019,6 @@ const struct ieee80211_ops rtl_ops = { .remove_interface = rtl_op_remove_interface, .config = rtl_op_config, .configure_filter = rtl_op_configure_filter, - .sta_add = rtl_op_sta_add, - .sta_remove = rtl_op_sta_remove, .set_key = rtl_op_set_key, .conf_tx = rtl_op_conf_tx, .bss_info_changed = rtl_op_bss_info_changed, @@ -1139,5 +1030,4 @@ const struct ieee80211_ops rtl_ops = { .sw_scan_start = rtl_op_sw_scan_start, .sw_scan_complete = rtl_op_sw_scan_complete, .rfkill_poll = rtl_op_rfkill_poll, - .flush = rtl_op_flush, }; diff --git a/trunk/drivers/net/wireless/rtlwifi/core.h b/trunk/drivers/net/wireless/rtlwifi/core.h index 4b247db2861d..0ef31c3c6196 100644 --- a/trunk/drivers/net/wireless/rtlwifi/core.h +++ b/trunk/drivers/net/wireless/rtlwifi/core.h @@ -24,7 +24,6 @@ * Hsinchu 300, Taiwan. * * Larry Finger - * *****************************************************************************/ #ifndef __RTL_CORE_H__ diff --git a/trunk/drivers/net/wireless/rtlwifi/efuse.c b/trunk/drivers/net/wireless/rtlwifi/efuse.c index 510d42edb8ca..590f14f45a89 100644 --- a/trunk/drivers/net/wireless/rtlwifi/efuse.c +++ b/trunk/drivers/net/wireless/rtlwifi/efuse.c @@ -52,6 +52,8 @@ static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { {11, 0, 0, 28} }; +static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, + u8 *pbuf); static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, u8 *value); static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, @@ -77,7 +79,7 @@ static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, u8 *targetdata); static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, u16 efuse_addr, u8 word_en, u8 *data); -static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, +static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate); static u16 efuse_get_current_size(struct ieee80211_hw *hw); static u8 efuse_calculate_word_cnts(u8 word_en); @@ -113,10 +115,8 @@ u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address) u8 bytetemp; u8 temp; u32 k = 0; - const u32 efuse_len = - rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - if (address < efuse_len) { + if (address < EFUSE_REAL_CONTENT_LEN) { temp = address & 0xFF; rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, temp); @@ -158,13 +158,11 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) u8 bytetemp; u8 temp; u32 k = 0; - const u32 efuse_len = - rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("Addr=%x Data =%x\n", address, value)); - if (address < efuse_len) { + if (address < EFUSE_REAL_CONTENT_LEN) { rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); temp = address & 0xFF; @@ -200,7 +198,7 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) } -void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) +static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 value32; @@ -235,28 +233,24 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 efuse_tbl[HWSET_MAX_SIZE]; + u8 efuse_tbl[EFUSE_MAP_LEN]; u8 rtemp8[1]; u16 efuse_addr = 0; u8 offset, wren; u16 i; u16 j; - const u16 efuse_max_section = - rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; - const u32 efuse_len = - rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; u16 efuse_utilized = 0; u8 efuse_usage; - if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { + if ((_offset + _size_byte) > EFUSE_MAP_LEN) { RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("read_efuse(): Invalid offset(%#x) with read " "bytes(%#x)!!\n", _offset, _size_byte)); return; } - for (i = 0; i < efuse_max_section; i++) + for (i = 0; i < EFUSE_MAX_SECTION; i++) for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) efuse_word[i][j] = 0xFFFF; @@ -268,10 +262,10 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_addr++; } - while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { + while ((*rtemp8 != 0xFF) && (efuse_addr < EFUSE_REAL_CONTENT_LEN)) { offset = ((*rtemp8 >> 4) & 0x0f); - if (offset < efuse_max_section) { + if (offset < EFUSE_MAX_SECTION) { wren = (*rtemp8 & 0x0f); RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, ("offset-%d Worden=%x\n", offset, wren)); @@ -287,7 +281,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_utilized++; efuse_word[offset][i] = (*rtemp8 & 0xff); - if (efuse_addr >= efuse_len) + if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) break; RTPRINT(rtlpriv, FEEPROM, @@ -300,7 +294,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_word[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); - if (efuse_addr >= efuse_len) + if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) break; } @@ -311,13 +305,13 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, ("Addr=%d\n", efuse_addr)); read_efuse_byte(hw, efuse_addr, rtemp8); - if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { + if (*rtemp8 != 0xFF && (efuse_addr < 512)) { efuse_utilized++; efuse_addr++; } } - for (i = 0; i < efuse_max_section; i++) { + for (i = 0; i < EFUSE_MAX_SECTION; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { efuse_tbl[(i * 8) + (j * 2)] = (efuse_word[i][j] & 0xff); @@ -330,7 +324,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) pbuf[i] = efuse_tbl[_offset + i]; rtlefuse->efuse_usedbytes = efuse_utilized; - efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len); + efuse_usage = (u8)((efuse_utilized * 100) / EFUSE_REAL_CONTENT_LEN); rtlefuse->efuse_usedpercentage = efuse_usage; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_utilized); @@ -344,11 +338,11 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 section_idx, i, Base; u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; - bool wordchanged, result = true; + bool bwordchanged, bresult = true; for (section_idx = 0; section_idx < 16; section_idx++) { Base = section_idx * 8; - wordchanged = false; + bwordchanged = false; for (i = 0; i < 8; i = i + 2) { if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != @@ -357,11 +351,11 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + 1])) { words_need++; - wordchanged = true; + bwordchanged = true; } } - if (wordchanged == true) + if (bwordchanged == true) hdr_num++; } @@ -370,14 +364,14 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) if ((totalbytes + efuse_used) >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) - result = false; + bresult = false; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("efuse_shadow_update_chk(): totalbytes(%#x), " "hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", totalbytes, hdr_num, words_need, efuse_used)); - return result; + return bresult; } void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, @@ -400,7 +394,7 @@ void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset, else if (type == 2) efuse_shadow_write_2byte(hw, offset, (u16) value); else if (type == 4) - efuse_shadow_write_4byte(hw, offset, value); + efuse_shadow_write_4byte(hw, offset, (u32) value); } @@ -484,10 +478,9 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - if (rtlefuse->autoload_failflag == true) - memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, - rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); - else + if (rtlefuse->autoload_failflag == true) { + memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, 128); + } else efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], @@ -579,7 +572,7 @@ static int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tmpidx = 0; - int result; + int bresult; rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff)); @@ -599,18 +592,19 @@ static int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) if (tmpidx < 100) { *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); - result = true; + bresult = true; } else { *data = 0xff; - result = false; + bresult = false; } - return result; + return bresult; } static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tmpidx = 0; + bool bresult; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("Addr = %x Data=%x\n", addr, data)); @@ -632,16 +626,17 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) } if (tmpidx < 100) - return true; + bresult = true; + else + bresult = false; - return false; + return bresult; } static void efuse_read_all_map(struct ieee80211_hw *hw, u8 * efuse) { - struct rtl_priv *rtlpriv = rtl_priv(hw); efuse_power_switch(hw, false, true); - read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); + read_efuse(hw, 0, 128, efuse); efuse_power_switch(hw, false, false); } @@ -649,7 +644,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, u8 efuse_data, u8 offset, u8 *tmpdata, u8 *readstate) { - bool dataempty = true; + bool bdataempty = true; u8 hoffset; u8 tmpidx; u8 hworden; @@ -665,13 +660,13 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, &efuse_data)) { tmpdata[tmpidx] = efuse_data; if (efuse_data != 0xff) - dataempty = true; + bdataempty = true; } } - if (dataempty == true) { + if (bdataempty == true) *readstate = PG_STATE_DATA; - } else { + else { *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; *readstate = PG_STATE_HEADER; } @@ -685,9 +680,12 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) { u8 readstate = PG_STATE_HEADER; - bool continual = true; + + bool bcontinual = true; + u8 efuse_data, word_cnts = 0; u16 efuse_addr = 0; + u8 hworden = 0; u8 tmpdata[8]; if (data == NULL) @@ -698,7 +696,7 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); - while (continual && (efuse_addr < EFUSE_MAX_SIZE)) { + while (bcontinual && (efuse_addr < EFUSE_MAX_SIZE)) { if (readstate & PG_STATE_HEADER) { if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) @@ -707,9 +705,9 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) offset, tmpdata, &readstate); else - continual = false; + bcontinual = false; } else if (readstate & PG_STATE_DATA) { - efuse_word_enable_data_read(0, tmpdata, data); + efuse_word_enable_data_read(hworden, tmpdata, data); efuse_addr = efuse_addr + (word_cnts * 2) + 1; readstate = PG_STATE_HEADER; } @@ -727,13 +725,13 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) } static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, - u8 efuse_data, u8 offset, int *continual, + u8 efuse_data, u8 offset, int *bcontinual, u8 *write_state, struct pgpkt_struct *target_pkt, - int *repeat_times, int *result, u8 word_en) + int *repeat_times, int *bresult, u8 word_en) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct tmp_pkt; - bool dataempty = true; + int bdataempty = true; u8 originaldata[8 * sizeof(u8)]; u8 badworden = 0x0F; u8 match_word_en, tmp_word_en; @@ -753,10 +751,10 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, u16 address = *efuse_addr + 1 + tmpindex; if (efuse_one_byte_read(hw, address, &efuse_data) && (efuse_data != 0xFF)) - dataempty = false; + bdataempty = false; } - if (dataempty == false) { + if (bdataempty == false) { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { @@ -801,25 +799,24 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, tmp_word_en &= (~BIT(1)); if ((target_pkt->word_en & BIT(2)) ^ - (match_word_en & BIT(2))) + (match_word_en & BIT(2))) tmp_word_en &= (~BIT(2)); if ((target_pkt->word_en & BIT(3)) ^ - (match_word_en & BIT(3))) + (match_word_en & BIT(3))) tmp_word_en &= (~BIT(3)); if ((tmp_word_en & 0x0F) != 0x0F) { *efuse_addr = efuse_get_current_size(hw); target_pkt->offset = offset; target_pkt->word_en = tmp_word_en; - } else { - *continual = false; - } + } else + *bcontinual = false; *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *continual = false; - *result = false; + *bcontinual = false; + *bresult = false; } } else { *efuse_addr += (2 * tmp_word_cnts) + 1; @@ -833,9 +830,9 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, - int *continual, u8 *write_state, + int *bcontinual, u8 *write_state, struct pgpkt_struct target_pkt, - int *repeat_times, int *result) + int *repeat_times, int *bresult) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct tmp_pkt; @@ -849,14 +846,14 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, efuse_one_byte_write(hw, *efuse_addr, pg_header); efuse_one_byte_read(hw, *efuse_addr, &tmp_header); - if (tmp_header == pg_header) { + if (tmp_header == pg_header) *write_state = PG_STATE_DATA; - } else if (tmp_header == 0xFF) { + else if (tmp_header == 0xFF) { *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *continual = false; - *result = false; + *bcontinual = false; + *bresult = false; } } else { tmp_pkt.offset = (tmp_header >> 4) & 0x0F; @@ -878,19 +875,17 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, reorg_worden, originaldata); *efuse_addr = efuse_get_current_size(hw); - } else { + } else *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - } - } else { + } else *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - } *write_state = PG_STATE_HEADER; *repeat_times += 1; if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *continual = false; - *result = false; + *bcontinual = false; + *bresult = false; } RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, @@ -904,7 +899,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct target_pkt; u8 write_state = PG_STATE_HEADER; - int continual = true, dataempty = true, result = true; + int bcontinual = true, bdataempty = true, bresult = true; u16 efuse_addr = 0; u8 efuse_data; u8 target_word_cnts = 0; @@ -928,11 +923,11 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse Power ON\n")); - while (continual && (efuse_addr < + while (bcontinual && (efuse_addr < (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { if (write_state == PG_STATE_HEADER) { - dataempty = true; + bdataempty = true; badworden = 0x0F; RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_HEADER\n")); @@ -941,30 +936,32 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, (efuse_data != 0xFF)) efuse_write_data_case1(hw, &efuse_addr, efuse_data, offset, - &continual, + &bcontinual, &write_state, &target_pkt, - &repeat_times, &result, + &repeat_times, &bresult, word_en); else efuse_write_data_case2(hw, &efuse_addr, - &continual, + &bcontinual, &write_state, target_pkt, &repeat_times, - &result); + &bresult); } else if (write_state == PG_STATE_DATA) { RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_DATA\n")); + badworden = 0x0f; badworden = efuse_word_enable_data_write(hw, efuse_addr + 1, target_pkt.word_en, target_pkt.data); if ((badworden & 0x0F) == 0x0F) { - continual = false; + bcontinual = false; } else { - efuse_addr += (2 * target_word_cnts) + 1; + efuse_addr = + efuse_addr + (2 * target_word_cnts) + 1; target_pkt.offset = offset; target_pkt.word_en = badworden; @@ -974,8 +971,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, write_state = PG_STATE_HEADER; repeat_times++; if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { - continual = false; - result = false; + bcontinual = false; + bresult = false; } RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_HEADER-3\n")); @@ -1075,15 +1072,13 @@ static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, return badworden; } -static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) +static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 tempval; u16 tmpV16; - if (pwrstate && (rtlhal->hw_type != - HARDWARE_TYPE_RTL8192SE)) { + if (pwrstate == true) { tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL]); if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { @@ -1111,29 +1106,20 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) } } - if (pwrstate) { - if (write) { + if (pwrstate == true) { + if (bwrite == true) { tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); - - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) { - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); - } - + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, (tempval | 0x80)); } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], - 0x03); - } - } else { - if (write) { + if (bwrite == true) { tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); @@ -1142,23 +1128,18 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) (tempval & 0x7F)); } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], - 0x02); - } - } } static u16 efuse_get_current_size(struct ieee80211_hw *hw) { - int continual = true; + int bcontinual = true; u16 efuse_addr = 0; u8 hoffset, hworden; u8 efuse_data, word_cnts; - while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) + while (bcontinual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) && (efuse_addr < EFUSE_MAX_SIZE)) { if (efuse_data != 0xFF) { hoffset = (efuse_data >> 4) & 0x0F; @@ -1166,7 +1147,7 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw) word_cnts = efuse_calculate_word_cnts(hworden); efuse_addr = efuse_addr + (word_cnts * 2) + 1; } else { - continual = false; + bcontinual = false; } } diff --git a/trunk/drivers/net/wireless/rtlwifi/efuse.h b/trunk/drivers/net/wireless/rtlwifi/efuse.h index 164dabaa7615..47774dd4c2a6 100644 --- a/trunk/drivers/net/wireless/rtlwifi/efuse.h +++ b/trunk/drivers/net/wireless/rtlwifi/efuse.h @@ -30,10 +30,9 @@ #ifndef __RTL_EFUSE_H_ #define __RTL_EFUSE_H_ -#define EFUSE_IC_ID_OFFSET 506 - #define EFUSE_REAL_CONTENT_LEN 512 #define EFUSE_MAP_LEN 128 +#define EFUSE_MAX_SECTION 16 #define EFUSE_MAX_WORD_UNIT 4 #define EFUSE_INIT_MAP 0 @@ -53,7 +52,6 @@ #define _PRE_EXECUTE_READ_CMD_ #define EFUSE_REPEAT_THRESHOLD_ 3 -#define EFUSE_ERROE_HANDLE 1 struct efuse_map { u8 offset; @@ -105,7 +103,6 @@ struct efuse_priv { u8 tx_power_g[14]; }; -extern void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); extern void efuse_initialize(struct ieee80211_hw *hw); extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.c b/trunk/drivers/net/wireless/rtlwifi/pci.c index 367d9b4ebd20..9cd7703c2a30 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.c +++ b/trunk/drivers/net/wireless/rtlwifi/pci.c @@ -32,7 +32,6 @@ #include "pci.h" #include "base.h" #include "ps.h" -#include "efuse.h" static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { INTEL_VENDOR_ID, @@ -41,31 +40,6 @@ static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { SIS_VENDOR_ID }; -static const u8 ac_to_hwq[] = { - VO_QUEUE, - VI_QUEUE, - BE_QUEUE, - BK_QUEUE -}; - -static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - __le16 fc = rtl_get_fc(skb); - u8 queue_index = skb_get_queue_mapping(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return BEACON_QUEUE; - if (ieee80211_is_mgmt(fc)) - return MGNT_QUEUE; - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) - if (ieee80211_is_nullfunc(fc)) - return HIGH_QUEUE; - - return ac_to_hwq[queue_index]; -} - /* Update PCI dependent default settings*/ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) { @@ -74,7 +48,6 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; - u8 init_aspm; ppsc->reg_rfps_level = 0; ppsc->support_aspm = 0; @@ -152,7 +125,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) bool support_backdoor = true; ppsc->support_aspm = support_aspm; - /*if (priv->oem_id == RT_CID_TOSHIBA && + /*if(priv->oem_id == RT_CID_TOSHIBA && !priv->ndis_adapter.amd_l1_patch) support_backdoor = false; */ @@ -172,13 +145,6 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) ("switch case not process\n")); break; } - - /* toshiba aspm issue, toshiba will set aspm selfly - * so we should not set aspm in driver */ - pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && - init_aspm == 0x43) - ppsc->support_aspm = false; } static bool _rtl_pci_platform_switch_device_pci_aspm( @@ -186,28 +152,28 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool bresult = false; - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) - value |= 0x40; + value |= 0x40; pci_write_config_byte(rtlpci->pdev, 0x80, value); - return false; + return bresult; } /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 buffer; + bool bresult = false; - pci_write_config_byte(rtlpci->pdev, 0x81, value); + buffer = value; - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) - udelay(100); + pci_write_config_byte(rtlpci->pdev, 0x81, value); + bresult = true; - return true; + return bresult; } /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ @@ -225,10 +191,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. pcibridge_linkctrlreg; u16 aspmlevel = 0; - u8 tmp_u1b = 0; - - if (!ppsc->support_aspm) - return; if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, @@ -242,8 +204,11 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) _rtl_pci_switch_clk_req(hw, 0x0); } - /*for promising device will in L0 state after an I/O. */ - pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); + if (1) { + /*for promising device will in L0 state after an I/O. */ + u8 tmp_u1b; + pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); + } /*Set corresponding value. */ aspmlevel |= BIT(0) | BIT(1); @@ -259,6 +224,7 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg); udelay(50); + } /* @@ -283,9 +249,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) u8 u_pcibridge_aspmsetting; u8 u_device_aspmsetting; - if (!ppsc->support_aspm) - return; - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, ("PCI(Bridge) UNKNOWN.\n")); @@ -330,7 +293,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); } - udelay(100); + udelay(200); } static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) @@ -367,13 +330,13 @@ static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; u8 linkctrl_reg; - u8 num4bbytes; + u8 num4bBytes; - num4bbytes = (capabilityoffset + 0x10) / 4; + num4bBytes = (capabilityoffset + 0x10) / 4; /*Read Link Control Register */ rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, - pcicfg_addrport + (num4bbytes << 2)); + pcicfg_addrport + (num4bBytes << 2)); rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg); pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; @@ -406,7 +369,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x70f, tmp); } -static void rtl_pci_init_aspm(struct ieee80211_hw *hw) +static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -420,6 +383,52 @@ static void rtl_pci_init_aspm(struct ieee80211_hw *hw) } +static void rtl_pci_init_aspm(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; + + _rtl_pci_initialize_adapter_common(hw); +} + static void _rtl_pci_io_handler_init(struct device *dev, struct ieee80211_hw *hw) { @@ -441,90 +450,6 @@ static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) { } -static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, - struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u8 additionlen = FCS_LEN; - struct sk_buff *next_skb; - - /* here open is 4, wep/tkip is 8, aes is 12*/ - if (info->control.hw_key) - additionlen += info->control.hw_key->icv_len; - - /* The most skb num is 6 */ - tcb_desc->empkt_num = 0; - spin_lock_bh(&rtlpriv->locks.waitq_lock); - skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { - struct ieee80211_tx_info *next_info; - - next_info = IEEE80211_SKB_CB(next_skb); - if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { - tcb_desc->empkt_len[tcb_desc->empkt_num] = - next_skb->len + additionlen; - tcb_desc->empkt_num++; - } else { - break; - } - - if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], - next_skb)) - break; - - if (tcb_desc->empkt_num >= 5) - break; - } - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - - return true; -} - -/* just for early mode now */ -static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct sk_buff *skb = NULL; - struct ieee80211_tx_info *info = NULL; - int tid; /* should be int */ - - if (!rtlpriv->rtlhal.earlymode_enable) - return; - - /* we juse use em for BE/BK/VI/VO */ - for (tid = 7; tid >= 0; tid--) { - u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)]; - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - while (!mac->act_scanning && - rtlpriv->psc.rfpwr_state == ERFON) { - struct rtl_tcb_desc tcb_desc; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - - spin_lock_bh(&rtlpriv->locks.waitq_lock); - if (!skb_queue_empty(&mac->skb_waitq[tid]) && - (ring->entries - skb_queue_len(&ring->queue) > 5)) { - skb = skb_dequeue(&mac->skb_waitq[tid]); - } else { - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - break; - } - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - - /* Some macaddr can't do early mode. like - * multicast/broadcast/no_qos data */ - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - _rtl_update_earlymode_info(hw, skb, - &tcb_desc, tid); - - rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); - } - } -} - - static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -536,8 +461,6 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) struct rtl_tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb; struct ieee80211_tx_info *info; - __le16 fc; - u8 tid; u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, HW_DESC_OWN); @@ -558,10 +481,6 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) HW_DESC_TXBUFF_ADDR), skb->len, PCI_DMA_TODEVICE); - /* remove early mode header */ - if (rtlpriv->rtlhal.earlymode_enable) - skb_pull(skb, EM_HDR_LEN); - RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, ("new ring->idx:%d, " "free: skb_queue_len:%d, free: seq:%x\n", @@ -569,30 +488,6 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb_queue_len(&ring->queue), *(u16 *) (skb->data + 22))); - if (prio == TXCMD_QUEUE) { - dev_kfree_skb(skb); - goto tx_status_ok; - - } - - /* for sw LPS, just after NULL skb send out, we can - * sure AP kown we are sleeped, our we should not let - * rf to sleep*/ - fc = rtl_get_fc(skb); - if (ieee80211_is_nullfunc(fc)) { - if (ieee80211_has_pm(fc)) { - rtlpriv->mac80211.offchan_deley = true; - rtlpriv->psc.state_inap = 1; - } else { - rtlpriv->psc.state_inap = 0; - } - } - - /* update tid tx pkt num */ - tid = rtl_get_tid(skb); - if (tid <= 7) - rtlpriv->link_info.tidtx_inperiod[tid]++; - info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); @@ -615,7 +510,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) skb_get_queue_mapping (skb)); } -tx_status_ok: + skb = NULL; } @@ -687,21 +582,23 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) *skb_trim(skb, skb->len - 4); */ - hdr = rtl_get_hdr(skb); - fc = rtl_get_fc(skb); + hdr = (struct ieee80211_hdr *)(skb->data); + fc = hdr->frame_control; - if (!stats.crc || !stats.hwerror) { + if (!stats.crc) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - if (is_broadcast_ether_addr(hdr->addr1)) { + if (is_broadcast_ether_addr(hdr->addr1)) ;/*TODO*/ - } else if (is_multicast_ether_addr(hdr->addr1)) { - ;/*TODO*/ - } else { - unicast = true; - rtlpriv->stats.rxbytesunicast += - skb->len; + else { + if (is_multicast_ether_addr(hdr->addr1)) + ;/*TODO*/ + else { + unicast = true; + rtlpriv->stats.rxbytesunicast += + skb->len; + } } rtl_is_special_data(hw, skb, false); @@ -715,38 +612,28 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) num_rx_inperiod++; } - /* for sw lps */ - rtl_swlps_beacon(hw, (void *)skb->data, - skb->len); - rtl_recognize_peer(hw, (void *)skb->data, - skb->len); - if ((rtlpriv->mac80211.opmode == - NL80211_IFTYPE_AP) && - (rtlpriv->rtlhal.current_bandtype == - BAND_ON_2_4G) && - (ieee80211_is_beacon(fc) || - ieee80211_is_probe_resp(fc))) { + if (unlikely(!rtl_action_proc(hw, skb, + false))) { dev_kfree_skb_any(skb); } else { - if (unlikely(!rtl_action_proc(hw, skb, - false))) { - dev_kfree_skb_any(skb); - } else { - struct sk_buff *uskb = NULL; - u8 *pdata; - uskb = dev_alloc_skb(skb->len - + 128); - memcpy(IEEE80211_SKB_RXCB(uskb), - &rx_status, - sizeof(rx_status)); - pdata = (u8 *)skb_put(uskb, - skb->len); - memcpy(pdata, skb->data, - skb->len); - dev_kfree_skb_any(skb); - - ieee80211_rx_irqsafe(hw, uskb); + struct sk_buff *uskb = NULL; + u8 *pdata; + uskb = dev_alloc_skb(skb->len + 128); + if (!uskb) { + RT_TRACE(rtlpriv, + (COMP_INTR | COMP_RECV), + DBG_EMERG, + ("can't alloc rx skb\n")); + goto done; } + memcpy(IEEE80211_SKB_RXCB(uskb), + &rx_status, + sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, skb->len); + memcpy(pdata, skb->data, skb->len); + dev_kfree_skb_any(skb); + + ieee80211_rx_irqsafe(hw, uskb); } } else { dev_kfree_skb_any(skb); @@ -761,7 +648,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) new_skb = dev_alloc_skb(rtlpci->rxbuffersize); if (unlikely(!new_skb)) { RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_DMESG, + DBG_EMERG, ("can't alloc skb for rx\n")); goto done; } @@ -779,7 +666,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) } done: - bufferaddress = (*((dma_addr_t *)skb->cb)); + bufferaddress = (u32)(*((dma_addr_t *) skb->cb)); tmp_one = 1; rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, HW_DESC_RXBUFF_ADDR, @@ -808,7 +695,6 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) struct ieee80211_hw *hw = dev_id; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); unsigned long flags; u32 inta = 0; u32 intb = 0; @@ -895,35 +781,22 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) _rtl_pci_tx_isr(hw, VO_QUEUE); } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { - if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { - rtlpriv->link_info.num_tx_inperiod++; - - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - ("CMD TX OK interrupt!\n")); - _rtl_pci_tx_isr(hw, TXCMD_QUEUE); - } - } - /*<2> Rx related */ if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n")); - _rtl_pci_rx_interrupt(hw); + tasklet_schedule(&rtlpriv->works.irq_tasklet); } if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx descriptor unavailable!\n")); - _rtl_pci_rx_interrupt(hw); + tasklet_schedule(&rtlpriv->works.irq_tasklet); } if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n")); - _rtl_pci_rx_interrupt(hw); - } - - if (rtlpriv->rtlhal.earlymode_enable) tasklet_schedule(&rtlpriv->works.irq_tasklet); + } spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); return IRQ_HANDLED; @@ -935,7 +808,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) { - _rtl_pci_tx_chk_waitq(hw); + _rtl_pci_rx_interrupt(hw); } static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) @@ -943,15 +816,14 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl8192_tx_ring *ring = NULL; + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; struct ieee80211_hdr *hdr = NULL; struct ieee80211_tx_info *info = NULL; struct sk_buff *pskb = NULL; struct rtl_tx_desc *pdesc = NULL; - struct rtl_tcb_desc tcb_desc; + unsigned int queue_index; u8 temp_one = 1; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); ring = &rtlpci->tx_ring[BEACON_QUEUE]; pskb = __skb_dequeue(&ring->queue); if (pskb) @@ -961,11 +833,14 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) pskb = ieee80211_beacon_get(hw, mac->vif); if (pskb == NULL) return; - hdr = rtl_get_hdr(pskb); + hdr = (struct ieee80211_hdr *)(pskb->data); info = IEEE80211_SKB_CB(pskb); + + queue_index = BEACON_QUEUE; + pdesc = &ring->desc[0]; rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, - info, pskb, BEACON_QUEUE, &tcb_desc); + info, pskb, queue_index); __skb_queue_tail(&ring->queue, pskb); @@ -1007,6 +882,7 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); rtlpci->up_first_time = true; rtlpci->being_init_adapter = false; @@ -1014,20 +890,31 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, rtlhal->hw = hw; rtlpci->pdev = pdev; + ppsc->inactiveps = false; + ppsc->leisure_ps = true; + ppsc->fwctrl_lps = true; + ppsc->reg_fwctrl_lps = 3; + ppsc->reg_max_lps_awakeintvl = 5; + + if (ppsc->reg_fwctrl_lps == 1) + ppsc->fwctrl_psmode = FW_PS_MIN_MODE; + else if (ppsc->reg_fwctrl_lps == 2) + ppsc->fwctrl_psmode = FW_PS_MAX_MODE; + else if (ppsc->reg_fwctrl_lps == 3) + ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; + /*Tx/Rx related var */ _rtl_pci_init_trx_var(hw); - /*IBSS*/ mac->beacon_interval = 100; + /*IBSS*/ mac->beacon_interval = 100; - /*AMPDU*/ - mac->min_space_cfg = 0; + /*AMPDU*/ mac->min_space_cfg = 0; mac->max_mss_density = 0; /*set sane AMPDU defaults */ mac->current_ampdu_density = 7; mac->current_ampdu_factor = 3; - /*QOS*/ - rtlpci->acm_method = eAcmWay2_SW; + /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; /*task */ tasklet_init(&rtlpriv->works.irq_tasklet, @@ -1068,8 +955,7 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, ("queue:%d, ring_addr:%p\n", prio, ring)); for (i = 0; i < entries; i++) { - nextdescaddress = (u32) dma + - ((i + 11) % entries) * + nextdescaddress = (u32) dma + ((i + 1) % entries) * sizeof(*ring); rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), @@ -1134,7 +1020,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - bufferaddress = (*((dma_addr_t *)skb->cb)); + bufferaddress = (u32)(*((dma_addr_t *)skb->cb)); rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXBUFF_ADDR, (u8 *)&bufferaddress); @@ -1317,74 +1203,73 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) return 0; } -static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, - struct sk_buff *skb) +static unsigned int _rtl_mac_to_hwqueue(__le16 fc, + unsigned int mac80211_queue_index) { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; - struct rtl_sta_info *sta_entry = NULL; - u8 tid = rtl_get_tid(skb); - - if (!sta) - return false; - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - - if (!rtlpriv->rtlhal.earlymode_enable) - return false; - if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) - return false; - if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) - return false; - if (tid > 7) - return false; - - /* maybe every tid should be checked */ - if (!rtlpriv->link_info.higher_busytxtraffic[tid]) - return false; - - spin_lock_bh(&rtlpriv->locks.waitq_lock); - skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); - spin_unlock_bh(&rtlpriv->locks.waitq_lock); + unsigned int hw_queue_index; - return true; + if (unlikely(ieee80211_is_beacon(fc))) { + hw_queue_index = BEACON_QUEUE; + goto out; + } + + if (ieee80211_is_mgmt(fc)) { + hw_queue_index = MGNT_QUEUE; + goto out; + } + + switch (mac80211_queue_index) { + case 0: + hw_queue_index = VO_QUEUE; + break; + case 1: + hw_queue_index = VI_QUEUE; + break; + case 2: + hw_queue_index = BE_QUEUE;; + break; + case 3: + hw_queue_index = BK_QUEUE; + break; + default: + hw_queue_index = BE_QUEUE; + RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", + mac80211_queue_index)); + break; + } + +out: + return hw_queue_index; } -static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc) +static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry = NULL; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; struct rtl8192_tx_ring *ring; struct rtl_tx_desc *pdesc; u8 idx; - u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb); + unsigned int queue_index, hw_queue; unsigned long flags; - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - __le16 fc = rtl_get_fc(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; u8 *pda_addr = hdr->addr1; struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); /*ssn */ + u8 *qc = NULL; u8 tid = 0; u16 seq_number = 0; u8 own; u8 temp_one = 1; - if (ieee80211_is_auth(fc)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); - rtl_ips_nic_on(hw); - } - - if (rtlpriv->psc.sw_ps_enabled) { - if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && - !ieee80211_has_pm(fc)) - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - } - + if (ieee80211_is_mgmt(fc)) + rtl_tx_mgmt_proc(hw, skb); rtl_action_proc(hw, skb, true); + queue_index = skb_get_queue_mapping(skb); + hw_queue = _rtl_mac_to_hwqueue(fc, queue_index); + if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; else if (is_broadcast_ether_addr(pda_addr)) @@ -1393,6 +1278,7 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->stats.txbytesunicast += skb->len; spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + ring = &rtlpci->tx_ring[hw_queue]; if (hw_queue != BEACON_QUEUE) idx = (ring->idx + skb_queue_len(&ring->queue)) % @@ -1415,30 +1301,43 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, return skb->len; } + /* + *if(ieee80211_is_nullfunc(fc)) { + * spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + * return 1; + *} + */ + if (ieee80211_is_data_qos(fc)) { - tid = rtl_get_tid(skb); - if (sta) { - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - seq_number = (le16_to_cpu(hdr->seq_ctrl) & - IEEE80211_SCTL_SEQ) >> 4; - seq_number += 1; - - if (!ieee80211_has_morefrags(hdr->frame_control)) - sta_entry->tids[tid].seq_number = seq_number; - } + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + + seq_number = mac->tids[tid].seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + /* + *hdr->seq_ctrl = hdr->seq_ctrl & + *cpu_to_le16(IEEE80211_SCTL_FRAG); + *hdr->seq_ctrl |= cpu_to_le16(seq_number); + */ + + seq_number += 1; } if (ieee80211_is_data(fc)) rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, - info, skb, hw_queue, ptcb_desc); + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, + info, skb, hw_queue); __skb_queue_tail(&ring->queue, skb); - rtlpriv->cfg->ops->set_desc((u8 *)pdesc, true, + rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, HW_DESC_OWN, (u8 *)&temp_one); + if (!ieee80211_has_morefrags(hdr->frame_control)) { + if (qc) + mac->tids[tid].seq_number = seq_number; + } if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && hw_queue != BEACON_QUEUE) { @@ -1460,35 +1359,6 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, return 0; } -static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i = 0; - int queue_id; - struct rtl8192_tx_ring *ring; - - for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { - u32 queue_len; - ring = &pcipriv->dev.tx_ring[queue_id]; - queue_len = skb_queue_len(&ring->queue); - if (queue_len == 0 || queue_id == BEACON_QUEUE || - queue_id == TXCMD_QUEUE) { - queue_id--; - continue; - } else { - msleep(20); - i++; - } - - /* we just wait 1s for all queues */ - if (rtlpriv->psc.rfpwr_state == ERFOFF || - is_hal_stop(rtlhal) || i >= 200) - return; - } -} - static void rtl_pci_deinit(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1607,13 +1477,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, struct pci_dev *bridge_pdev = pdev->bus->self; u16 venderid; u16 deviceid; - u8 revisionid; u16 irqline; u8 tmp; venderid = pdev->vendor; deviceid = pdev->device; - pci_read_config_byte(pdev, 0x8, &revisionid); pci_read_config_word(pdev, 0x3C, &irqline); if (deviceid == RTL_PCI_8192_DID || @@ -1624,7 +1492,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, deviceid == RTL_PCI_8173_DID || deviceid == RTL_PCI_8172_DID || deviceid == RTL_PCI_8171_DID) { - switch (revisionid) { + switch (pdev->revision) { case RTL_PCI_REVISION_ID_8192PCIE: RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("8192 PCI-E is found - " @@ -1653,12 +1521,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("8192C PCI-E is found - " "vid/did=%x/%x\n", venderid, deviceid)); - } else if (deviceid == RTL_PCI_8192DE_DID || - deviceid == RTL_PCI_8192DE_DID2) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - ("8192D PCI-E is found - " - "vid/did=%x/%x\n", venderid, deviceid)); } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Err: Unknown device -" @@ -1667,25 +1529,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { - if (revisionid == 0 || revisionid == 1) { - if (revisionid == 0) { - RT_TRACE(rtlpriv, COMP_INIT, - DBG_LOUD, ("Find 92DE MAC0.\n")); - rtlhal->interfaceindex = 0; - } else if (revisionid == 1) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - ("Find 92DE MAC1.\n")); - rtlhal->interfaceindex = 1; - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - ("Unknown device - " - "VendorID/DeviceID=%x/%x, Revision=%x\n", - venderid, deviceid, revisionid)); - rtlhal->interfaceindex = 0; - } - } /*find bus info */ pcipriv->ndis_adapter.busnumber = pdev->bus->number; pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); @@ -1711,12 +1554,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, PCI_SLOT(bridge_pdev->devfn); pcipriv->ndis_adapter.pcibridge_funcnum = PCI_FUNC(bridge_pdev->devfn); + pcipriv->ndis_adapter.pcibridge_pciehdr_offset = + pci_pcie_cap(bridge_pdev); pcipriv->ndis_adapter.pcicfg_addrport = (pcipriv->ndis_adapter.pcibridge_busnum << 16) | (pcipriv->ndis_adapter.pcibridge_devnum << 11) | (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31); - pcipriv->ndis_adapter.pcibridge_pciehdr_offset = - pci_pcie_cap(bridge_pdev); pcipriv->ndis_adapter.num4bytes = (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; @@ -1799,11 +1642,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pcipriv = (void *)rtlpriv->priv; pcipriv->dev.pdev = pdev; - /* init cfg & intf_ops */ - rtlpriv->rtlhal.interface = INTF_PCI; - rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); - rtlpriv->intf_ops = &rtl_pci_ops; - /* *init dbgp flags before all *other functions, because we will @@ -1821,14 +1659,13 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, return err; } - pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); - pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); - pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id); + pmem_start = pci_resource_start(pdev, 2); + pmem_len = pci_resource_len(pdev, 2); + pmem_flags = pci_resource_flags(pdev, 2); /*shared mem start */ rtlpriv->io.pci_mem_start = - (unsigned long)pci_iomap(pdev, - rtlpriv->cfg->bar_id, pmem_len); + (unsigned long)pci_iomap(pdev, 2, pmem_len); if (rtlpriv->io.pci_mem_start == 0) { RT_ASSERT(false, ("Can't map PCI mem\n")); goto fail2; @@ -1847,6 +1684,11 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x04, 0x06); pci_write_config_byte(pdev, 0x04, 0x07); + /* init cfg & intf_ops */ + rtlpriv->rtlhal.interface = INTF_PCI; + rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); + rtlpriv->intf_ops = &rtl_pci_ops; + /* find adapter */ _rtl_pci_find_adapter(pdev, hw); @@ -1964,6 +1806,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev) rtl_pci_deinit(hw); rtl_deinit_core(hw); + rtlpriv->cfg->ops->deinit_sw_leds(hw); _rtl_pci_io_handler_release(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); @@ -1978,9 +1821,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) } pci_disable_device(pdev); - - rtl_pci_disable_aspm(hw); - pci_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); @@ -2004,15 +1844,10 @@ no need to call hw_disable here. ****************************************/ int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state) { - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->cfg->ops->hw_suspend(hw); - rtl_deinit_rfkill(hw); - pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); + return 0; } EXPORT_SYMBOL(rtl_pci_suspend); @@ -2020,8 +1855,6 @@ EXPORT_SYMBOL(rtl_pci_suspend); int rtl_pci_resume(struct pci_dev *pdev) { int ret; - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct rtl_priv *rtlpriv = rtl_priv(hw); pci_set_power_state(pdev, PCI_D0); ret = pci_enable_device(pdev); @@ -2032,20 +1865,15 @@ int rtl_pci_resume(struct pci_dev *pdev) pci_restore_state(pdev); - rtlpriv->cfg->ops->hw_resume(hw); - rtl_init_rfkill(hw); return 0; } EXPORT_SYMBOL(rtl_pci_resume); struct rtl_intf_ops rtl_pci_ops = { - .read_efuse_byte = read_efuse_byte, .adapter_start = rtl_pci_start, .adapter_stop = rtl_pci_stop, .adapter_tx = rtl_pci_tx, - .flush = rtl_pci_flush, .reset_trx_ring = rtl_pci_reset_trx_ring, - .waitq_insert = rtl_pci_tx_chk_waitq_insert, .disable_aspm = rtl_pci_disable_aspm, .enable_aspm = rtl_pci_enable_aspm, diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.h b/trunk/drivers/net/wireless/rtlwifi/pci.h index 671b1f5aa0cf..0caa81429726 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.h +++ b/trunk/drivers/net/wireless/rtlwifi/pci.h @@ -102,8 +102,8 @@ #define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ #define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ -#define RTL_PCI_8192DE_DID 0x8193 /*8192de */ -#define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ +#define RTL_PCI_8192DE_DID 0x092D /*8192ce */ +#define RTL_PCI_8192DU_DID 0x092D /*8192ce */ /*8192 support 16 pages of IO registers*/ #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 @@ -129,11 +129,6 @@ enum pci_bridge_vendor { PCI_BRIDGE_VENDOR_MAX, }; -struct rtl_pci_capabilities_header { - u8 capability_id; - u8 next; -}; - struct rtl_rx_desc { u32 dword[8]; } __packed; @@ -166,9 +161,7 @@ struct rtl_pci { bool driver_is_goingto_unload; bool up_first_time; - bool first_init; bool being_init_adapter; - bool init_ready; bool irq_enabled; /*Tx */ @@ -199,14 +192,11 @@ struct rtl_pci { u8 const_devicepci_aspm_setting; /*If it supports ASPM, Offset[560h] = 0x40, otherwise Offset[560h] = 0x00. */ - bool support_aspm; - bool support_backdoor; + bool b_support_aspm; + bool b_support_backdoor; /*QOS & EDCA */ enum acm_method acm_method; - - u16 shortretry_limit; - u16 longretry_limit; }; struct mp_adapter { @@ -237,7 +227,6 @@ struct rtl_pci_priv { struct rtl_pci dev; struct mp_adapter ndis_adapter; struct rtl_led_ctl ledctl; - struct bt_coexist_info bt_coexist; }; #define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) diff --git a/trunk/drivers/net/wireless/rtlwifi/ps.c b/trunk/drivers/net/wireless/rtlwifi/ps.c index 2bb71195e976..6b7e217b6b89 100644 --- a/trunk/drivers/net/wireless/rtlwifi/ps.c +++ b/trunk/drivers/net/wireless/rtlwifi/ps.c @@ -36,6 +36,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool init_status = true; /*<1> reset trx ring */ if (rtlhal->interface == INTF_PCI) @@ -48,6 +49,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<2> Enable Adapter */ rtlpriv->cfg->ops->hw_init(hw); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + /*init_status = false; */ /*<3> Enable Interrupt */ rtlpriv->cfg->ops->enable_interrupt(hw); @@ -55,12 +57,13 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /* */ rtl_watch_dog_timer_callback((unsigned long)hw); - return true; + return init_status; } EXPORT_SYMBOL(rtl_ps_enable_nic); bool rtl_ps_disable_nic(struct ieee80211_hw *hw) { + bool status = true; struct rtl_priv *rtlpriv = rtl_priv(hw); /*<1> Stop all timer */ @@ -72,7 +75,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw) /*<3> Disable Adapter */ rtlpriv->cfg->ops->hw_disable(hw); - return true; + return status; } EXPORT_SYMBOL(rtl_ps_disable_nic); @@ -190,13 +193,12 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) ppsc->swrf_processing = true; - if (ppsc->inactive_pwrstate == ERFOFF && - rtlhal->interface == INTF_PCI) { + if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); } } @@ -205,10 +207,9 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) if (ppsc->inactive_pwrstate == ERFOFF && rtlhal->interface == INTF_PCI) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && - !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); } } @@ -232,9 +233,6 @@ void rtl_ips_nic_off_wq_callback(void *data) return; } - if (mac->link_state > MAC80211_NOLINK) - return; - if (is_hal_stop(rtlhal)) return; @@ -286,14 +284,10 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) void rtl_ips_nic_on(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rf_pwrstate rtstate; unsigned long flags; - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); if (ppsc->inactiveps) { @@ -376,7 +370,8 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) * mode and set RPWM to turn RF on. */ - if ((ppsc->fwctrl_lps) && ppsc->report_linked) { + if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) && + ppsc->report_linked) { bool fw_current_inps; if (ppsc->dot11_psmode == EACTIVE) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, @@ -430,7 +425,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned long flag; - if (!ppsc->fwctrl_lps) + if (!(ppsc->fwctrl_lps && ppsc->leisure_ps)) return; if (rtlpriv->sec.being_setkey) @@ -451,16 +446,17 @@ void rtl_lps_enter(struct ieee80211_hw *hw) spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - /* Idle for a while if we connect to AP a while ago. */ - if (mac->cnt_after_linked >= 2) { - if (ppsc->dot11_psmode == EACTIVE) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + if (ppsc->leisure_ps) { + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Enter 802.11 power save mode...\n")); - rtl_lps_set_psmode(hw, EAUTOPS); + rtl_lps_set_psmode(hw, EAUTOPS); + } } } - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } @@ -474,17 +470,17 @@ void rtl_lps_leave(struct ieee80211_hw *hw) spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - if (ppsc->fwctrl_lps) { + if (ppsc->fwctrl_lps && ppsc->leisure_ps) { if (ppsc->dot11_psmode != EACTIVE) { /*FIX ME */ rtlpriv->cfg->ops->enable_interrupt(hw); if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && - RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) && rtlhal->interface == INTF_PCI) { rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM); } RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, @@ -495,214 +491,3 @@ void rtl_lps_leave(struct ieee80211_hw *hw) } spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); } - -/* For sw LPS*/ -void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (void *) data; - struct ieee80211_tim_ie *tim_ie; - u8 *tim; - u8 tim_len; - bool u_buffed; - bool m_buffed; - - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - - if (!rtlpriv->psc.swctrl_lps) - return; - - if (rtlpriv->mac80211.link_state != MAC80211_LINKED) - return; - - if (!rtlpriv->psc.sw_ps_enabled) - return; - - if (rtlpriv->psc.fwctrl_lps) - return; - - if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) - return; - - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - - /* min. beacon length + FCS_LEN */ - if (len <= 40 + FCS_LEN) - return; - - /* and only beacons from the associated BSSID, please */ - if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) - return; - - rtlpriv->psc.last_beacon = jiffies; - - tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); - if (!tim) - return; - - if (tim[1] < sizeof(*tim_ie)) - return; - - tim_len = tim[1]; - tim_ie = (struct ieee80211_tim_ie *) &tim[2]; - - if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period)) - rtlpriv->psc.dtim_counter = tim_ie->dtim_count; - - /* Check whenever the PHY can be turned off again. */ - - /* 1. What about buffered unicast traffic for our AID? */ - u_buffed = ieee80211_check_tim(tim_ie, tim_len, - rtlpriv->mac80211.assoc_id); - - /* 2. Maybe the AP wants to send multicast/broadcast data? */ - m_buffed = tim_ie->bitmap_ctrl & 0x01; - rtlpriv->psc.multi_buffered = m_buffed; - - /* unicast will process by mac80211 through - * set ~IEEE80211_CONF_PS, So we just check - * multicast frames here */ - if (!m_buffed) { - /* back to low-power land. and delay is - * prevent null power save frame tx fail */ - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.ps_work, MSECS(5)); - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("u_bufferd: %x, " - "m_buffered: %x\n", u_buffed, m_buffed)); - } -} - -void rtl_swlps_rf_awake(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - unsigned long flag; - - if (!rtlpriv->psc.swctrl_lps) - return; - if (mac->link_state != MAC80211_LINKED) - return; - - if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && - RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); -} - -void rtl_swlps_rfon_wq_callback(void *data) -{ - struct rtl_works *rtlworks = - container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq); - struct ieee80211_hw *hw = rtlworks->hw; - - rtl_swlps_rf_awake(hw); -} - -void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - unsigned long flag; - u8 sleep_intv; - - if (!rtlpriv->psc.sw_ps_enabled) - return; - - if ((rtlpriv->sec.being_setkey) || - (mac->opmode == NL80211_IFTYPE_ADHOC)) - return; - - /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ - if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) - return; - - if (rtlpriv->link_info.busytraffic) - return; - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - if (rtlpriv->psc.rfchange_inprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - return; - } - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false); - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && - !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - - /* here is power save alg, when this beacon is DTIM - * we will set sleep time to dtim_period * n; - * when this beacon is not DTIM, we will set sleep - * time to sleep_intv = rtlpriv->psc.dtim_counter or - * MAX_SW_LPS_SLEEP_INTV(default set to 5) */ - - if (rtlpriv->psc.dtim_counter == 0) { - if (hw->conf.ps_dtim_period == 1) - sleep_intv = hw->conf.ps_dtim_period * 2; - else - sleep_intv = hw->conf.ps_dtim_period; - } else { - sleep_intv = rtlpriv->psc.dtim_counter; - } - - if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) - sleep_intv = MAX_SW_LPS_SLEEP_INTV; - - /* this print should always be dtim_conter = 0 & - * sleep = dtim_period, that meaons, we should - * awake before every dtim */ - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - ("dtim_counter:%x will sleep :%d" - " beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv)); - - /* we tested that 40ms is enough for sw & hw sw delay */ - queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, - MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); -} - - -void rtl_swlps_wq_callback(void *data) -{ - struct rtl_works *rtlworks = container_of_dwork_rtl(data, - struct rtl_works, - ps_work); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool ps = false; - - ps = (hw->conf.flags & IEEE80211_CONF_PS); - - /* we can sleep after ps null send ok */ - if (rtlpriv->psc.state_inap) { - rtl_swlps_rf_sleep(hw); - - if (rtlpriv->psc.state && !ps) { - rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies - - rtlpriv->psc.last_action); - } - - if (ps) - rtlpriv->psc.last_slept = jiffies; - - rtlpriv->psc.last_action = jiffies; - rtlpriv->psc.state = ps; - } -} diff --git a/trunk/drivers/net/wireless/rtlwifi/ps.h b/trunk/drivers/net/wireless/rtlwifi/ps.h index e3bf89840370..ae56da801a23 100644 --- a/trunk/drivers/net/wireless/rtlwifi/ps.h +++ b/trunk/drivers/net/wireless/rtlwifi/ps.h @@ -30,8 +30,6 @@ #ifndef __REALTEK_RTL_PCI_PS_H__ #define __REALTEK_RTL_PCI_PS_H__ -#define MAX_SW_LPS_SLEEP_INTV 5 - bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, enum rf_pwrstate state_toset, u32 changesource, bool protect_or_not); @@ -42,11 +40,4 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw); void rtl_ips_nic_off_wq_callback(void *data); void rtl_lps_enter(struct ieee80211_hw *hw); void rtl_lps_leave(struct ieee80211_hw *hw); - -void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len); -void rtl_swlps_wq_callback(void *data); -void rtl_swlps_rfon_wq_callback(void *data); -void rtl_swlps_rf_awake(struct ieee80211_hw *hw); -void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); - #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rc.c b/trunk/drivers/net/wireless/rtlwifi/rc.c index 30da68a77786..91634107434a 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rc.c +++ b/trunk/drivers/net/wireless/rtlwifi/rc.c @@ -38,14 +38,17 @@ *CCK11M or OFDM_54M based on wireless mode. */ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, - struct ieee80211_sta *sta, struct sk_buff *skb, bool not_data) { struct rtl_mac *rtlmac = rtl_mac(rtlpriv); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_sta_info *sta_entry = NULL; - u8 wireless_mode = 0; + + /* + *mgt use 1M, although we have check it + *before this function use rate_control_send_low, + *we still check it here + */ + if (not_data) + return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; /* *this rate is no use for true rate, firmware @@ -54,78 +57,35 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, *2.in rtl_get_tcb_desc when we check rate is * 1M we will not use FW rate but user rate. */ - if (rtlmac->opmode == NL80211_IFTYPE_AP || - rtlmac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) { - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - wireless_mode = sta_entry->wireless_mode; - } else { - return 0; - } - } else { - wireless_mode = rtlmac->mode; - } - - if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true) || - not_data) { - return 0; + if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true)) { + return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; } else { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - if (wireless_mode == WIRELESS_MODE_B) { - return B_MODE_MAX_RIX; - } else if (wireless_mode == WIRELESS_MODE_G) { - return G_MODE_MAX_RIX; - } else { - if (get_rf_type(rtlphy) != RF_2T2R) - return N_MODE_MCS7_RIX; - else - return N_MODE_MCS15_RIX; - } - } else { - if (wireless_mode == WIRELESS_MODE_A) { - return A_MODE_MAX_RIX; - } else { - if (get_rf_type(rtlphy) != RF_2T2R) - return N_MODE_MCS7_RIX; - else - return N_MODE_MCS15_RIX; - } - } + if (rtlmac->mode == WIRELESS_MODE_B) + return rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; + else + return rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; } } static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, - struct ieee80211_sta *sta, struct ieee80211_tx_rate *rate, struct ieee80211_tx_rate_control *txrc, - u8 tries, char rix, int rtsctsenable, + u8 tries, u8 rix, int rtsctsenable, bool not_data) { struct rtl_mac *mac = rtl_mac(rtlpriv); - u8 sgi_20 = 0, sgi_40 = 0; - if (sta) { - sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; - sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; - } rate->count = tries; - rate->idx = rix >= 0x00 ? rix : 0x00; + rate->idx = (rix > 0x2) ? rix : 0x2; if (!not_data) { if (txrc->short_preamble) rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta && (sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - } else { - if (mac->bw_40) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - } - if (sgi_20 || sgi_40) + if (mac->bw_40) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (mac->sgi_20 || mac->sgi_40) rate->flags |= IEEE80211_TX_RC_SHORT_GI; - if (sta && sta->ht_cap.ht_supported) + if (mac->ht_enable) rate->flags |= IEEE80211_TX_RC_MCS; } } @@ -137,39 +97,39 @@ static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; - __le16 fc = rtl_get_fc(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; u8 try_per_rate, i, rix; bool not_data = !ieee80211_is_data(fc); if (rate_control_send_low(sta, priv_sta, txrc)) return; - rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); + rix = _rtl_rc_get_highest_rix(rtlpriv, skb, not_data); + try_per_rate = 1; - _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, + _rtl_rc_rate_set_series(rtlpriv, &rates[0], txrc, try_per_rate, rix, 1, not_data); if (!not_data) { for (i = 1; i < 4; i++) - _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], + _rtl_rc_rate_set_series(rtlpriv, &rates[i], txrc, i, (rix - i), 1, not_data); } } -static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, - struct rtl_sta_info *sta_entry, u16 tid) +static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, u16 tid) { struct rtl_mac *mac = rtl_mac(rtlpriv); if (mac->act_scanning) return false; - if (mac->opmode == NL80211_IFTYPE_STATION && - mac->cnt_after_linked < 3) + if (mac->cnt_after_linked < 3) return false; - if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) + if (mac->tids[tid].agg.agg_state == RTL_AGG_OFF) return true; return false; @@ -183,9 +143,11 @@ static void rtl_tx_status(void *ppriv, { struct rtl_priv *rtlpriv = ppriv; struct rtl_mac *mac = rtl_mac(rtlpriv); - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - __le16 fc = rtl_get_fc(skb); - struct rtl_sta_info *sta_entry; + struct ieee80211_hdr *hdr; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; if (!priv_sta || !ieee80211_is_data(fc)) return; @@ -197,21 +159,17 @@ static void rtl_tx_status(void *ppriv, || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) return; - if (sta) { - /* Check if aggregation has to be enabled for this tid */ - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - if ((sta->ht_cap.ht_supported == true) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 tid = rtl_get_tid(skb); - if (_rtl_tx_aggr_check(rtlpriv, sta_entry, - tid)) { - sta_entry->tids[tid].agg.agg_state = - RTL_AGG_PROGRESS; - ieee80211_start_tx_ba_session(sta, - tid, 5000); - } - } + /* Check if aggregation has to be enabled for this tid */ + if (conf_is_ht(&mac->hw->conf) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + + if (_rtl_tx_aggr_check(rtlpriv, tid)) + ieee80211_start_tx_ba_session(sta, tid, 5000); } } } @@ -220,6 +178,43 @@ static void rtl_rate_init(void *ppriv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { + struct rtl_priv *rtlpriv = ppriv; + struct rtl_mac *mac = rtl_mac(rtlpriv); + u8 is_ht = conf_is_ht(&mac->hw->conf); + + if ((mac->opmode == NL80211_IFTYPE_STATION) || + (mac->opmode == NL80211_IFTYPE_MESH_POINT) || + (mac->opmode == NL80211_IFTYPE_ADHOC)) { + + switch (sband->band) { + case IEEE80211_BAND_2GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_G; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + case IEEE80211_BAND_5GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_A; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("Invalid band\n")); + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + } + + RT_TRACE(rtlpriv, COMP_RATE, DBG_DMESG, + ("Choosing rate table index: %d\n", + rtlpriv->rate_priv->cur_ratetab_idx)); + + } + } static void rtl_rate_update(void *ppriv, @@ -228,6 +223,49 @@ static void rtl_rate_update(void *ppriv, u32 changed, enum nl80211_channel_type oper_chan_type) { + struct rtl_priv *rtlpriv = ppriv; + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + bool oper_cw40 = false, oper_sgi40; + bool local_cw40 = mac->bw_40; + bool local_sgi40 = mac->sgi_40; + u8 is_ht = conf_is_ht(&mac->hw->conf); + + if (changed & IEEE80211_RC_HT_CHANGED) { + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || + rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) + oper_cw40 = true; + + oper_sgi40 = mac->sgi_40; + + if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { + switch (sband->band) { + case IEEE80211_BAND_2GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_G; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + case IEEE80211_BAND_5GHZ: + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_A; + if (is_ht) + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Invalid band\n")); + rtlpriv->rate_priv->cur_ratetab_idx = + RATR_INX_WIRELESS_NGB; + break; + } + } + } } static void *rtl_rate_alloc(struct ieee80211_hw *hw, diff --git a/trunk/drivers/net/wireless/rtlwifi/rc.h b/trunk/drivers/net/wireless/rtlwifi/rc.h index 4afa2c20adcf..b4667c035f0b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rc.h +++ b/trunk/drivers/net/wireless/rtlwifi/rc.h @@ -30,15 +30,8 @@ #ifndef __RTL_RC_H__ #define __RTL_RC_H__ -#define B_MODE_MAX_RIX 3 -#define G_MODE_MAX_RIX 11 -#define A_MODE_MAX_RIX 7 - -/* in mac80211 mcs0-mcs15 is idx0-idx15*/ -#define N_MODE_MCS7_RIX 7 -#define N_MODE_MCS15_RIX 15 - struct rtl_rate_priv { + u8 cur_ratetab_idx; u8 ht_cap; }; diff --git a/trunk/drivers/net/wireless/rtlwifi/regd.c b/trunk/drivers/net/wireless/rtlwifi/regd.c index 714858abc4ac..3336ca999dfd 100644 --- a/trunk/drivers/net/wireless/rtlwifi/regd.c +++ b/trunk/drivers/net/wireless/rtlwifi/regd.c @@ -66,83 +66,31 @@ static struct country_code_to_enum_rd allCountries[] = { NL80211_RRF_PASSIVE_SCAN | \ NL80211_RRF_NO_OFDM) -/* 5G chan 36 - chan 64*/ -#define RTL819x_5GHZ_5150_5350 \ - REG_RULE(5150-10, 5350+10, 40, 0, 30, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) - -/* 5G chan 100 - chan 165*/ -#define RTL819x_5GHZ_5470_5850 \ - REG_RULE(5470-10, 5850+10, 40, 0, 30, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) - -/* 5G chan 149 - chan 165*/ -#define RTL819x_5GHZ_5725_5850 \ - REG_RULE(5725-10, 5850+10, 40, 0, 30, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_IBSS) - -#define RTL819x_5GHZ_ALL \ - (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) - static const struct ieee80211_regdomain rtl_regdom_11 = { .n_reg_rules = 1, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_12_13 = { - .n_reg_rules = 2, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_no_midband = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_5GHZ_5150_5350, - RTL819x_5GHZ_5725_5850, - } + } }; -static const struct ieee80211_regdomain rtl_regdom_60_64 = { +static const struct ieee80211_regdomain rtl_regdom_global = { .n_reg_rules = 3, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_5GHZ_5725_5850, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_14_60_64 = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_2GHZ_CH14, - RTL819x_5GHZ_5725_5850, - } + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + } }; -static const struct ieee80211_regdomain rtl_regdom_14 = { - .n_reg_rules = 3, +static const struct ieee80211_regdomain rtl_regdom_world = { + .n_reg_rules = 2, .alpha2 = "99", .reg_rules = { RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_2GHZ_CH14, - } + RTL819x_2GHZ_CH12_13, + } }; static bool _rtl_is_radar_freq(u16 center_freq) @@ -214,8 +162,6 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, u32 bandwidth = 0; int r; - if (!wiphy->bands[IEEE80211_BAND_2GHZ]) - return; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; /* @@ -346,26 +292,25 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( { switch (reg->country_code) { case COUNTRY_CODE_FCC: - return &rtl_regdom_no_midband; case COUNTRY_CODE_IC: return &rtl_regdom_11; case COUNTRY_CODE_ETSI: - case COUNTRY_CODE_TELEC_NETGEAR: - return &rtl_regdom_60_64; case COUNTRY_CODE_SPAIN: case COUNTRY_CODE_FRANCE: case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_WORLD_WIDE_13: - return &rtl_regdom_12_13; + case COUNTRY_CODE_TELEC_NETGEAR: + return &rtl_regdom_world; case COUNTRY_CODE_MKK: case COUNTRY_CODE_MKK1: case COUNTRY_CODE_TELEC: case COUNTRY_CODE_MIC: - return &rtl_regdom_14_60_64; + return &rtl_regdom_global; case COUNTRY_CODE_GLOBAL_DOMAIN: - return &rtl_regdom_14; + return &rtl_regdom_global; + case COUNTRY_CODE_WORLD_WIDE_13: + return &rtl_regdom_world; default: - return &rtl_regdom_no_midband; + return &rtl_regdom_world; } } @@ -378,11 +323,9 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, const struct ieee80211_regdomain *regd; wiphy->reg_notifier = reg_notifier; - wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; - regd = _rtl_regdomain_select(reg); wiphy_apply_custom_regulatory(wiphy, regd); _rtl_reg_apply_radar_flags(wiphy); @@ -412,8 +355,8 @@ int rtl_regd_init(struct ieee80211_hw *hw, if (wiphy == NULL || &rtlpriv->regd == NULL) return -EINVAL; - /* init country_code from efuse channel plan */ - rtlpriv->regd.country_code = rtlpriv->efuse.channel_plan; + /* force the channel plan to world wide 13 */ + rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, (KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", @@ -430,8 +373,8 @@ int rtl_regd_init(struct ieee80211_hw *hw, country = _rtl_regd_find_country(rtlpriv->regd.country_code); if (country) { - rtlpriv->regd.alpha2[0] = country->iso_name[0]; - rtlpriv->regd.alpha2[1] = country->iso_name[1]; + rtlpriv->regd.alpha2[0] = country->isoName[0]; + rtlpriv->regd.alpha2[1] = country->isoName[1]; } else { rtlpriv->regd.alpha2[0] = '0'; rtlpriv->regd.alpha2[1] = '0'; diff --git a/trunk/drivers/net/wireless/rtlwifi/regd.h b/trunk/drivers/net/wireless/rtlwifi/regd.h index d23118938fac..4cdbc4ae76d4 100644 --- a/trunk/drivers/net/wireless/rtlwifi/regd.h +++ b/trunk/drivers/net/wireless/rtlwifi/regd.h @@ -32,7 +32,7 @@ struct country_code_to_enum_rd { u16 countrycode; - const char *iso_name; + const char *isoName; }; enum country_code_type_t { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 97183829b9be..bb023274414c 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -28,26 +28,10 @@ *****************************************************************************/ #include "dm_common.h" -#include "phy_common.h" -#include "../pci.h" -#include "../base.h" struct dig_t dm_digtable; static struct ps_t dm_pstable; -#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) -#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) -#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) - -#define RTLPRIV (struct rtl_priv *) -#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ - ((RTLPRIV(_priv))->mac80211.opmode == \ - NL80211_IFTYPE_ADHOC) ? \ - ((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \ - ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb) - static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { 0x7f8001fe, 0x788001e2, @@ -320,7 +304,7 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) { - static u8 initialized; /* initialized to false */ + static u8 binitialized; /* initialized to false */ struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; @@ -331,11 +315,11 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) if ((multi_sta == false) || (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT)) { - initialized = false; + binitialized = false; dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; return; - } else if (initialized == false) { - initialized = true; + } else if (binitialized == false) { + binitialized = true; dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; dm_digtable.cur_igvalue = 0x20; rtl92c_dm_write_dig(hw); @@ -477,7 +461,10 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) if (mac->act_scanning == true) return; - if (mac->link_state >= MAC80211_LINKED) + if ((mac->link_state > MAC80211_NOLINK) && + (mac->link_state < MAC80211_LINKED)) + dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT; + else if (mac->link_state >= MAC80211_LINKED) dm_digtable.cursta_connectctate = DIG_STA_CONNECT; else dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT; @@ -575,42 +562,23 @@ EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo); static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - static u64 last_txok_cnt; static u64 last_rxok_cnt; - static u32 last_bt_edca_ul; - static u32 last_bt_edca_dl; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; + u64 cur_txok_cnt; + u64 cur_rxok_cnt; u32 edca_be_ul = 0x5ea42b; u32 edca_be_dl = 0x5ea42b; - bool bt_change_edca = false; - - if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || - (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { - rtlpriv->dm.current_turbo_edca = false; - last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; - last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; - } - if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { - edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; - bt_change_edca = true; - } - - if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { - edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; - bt_change_edca = true; - } + if (mac->opmode == NL80211_IFTYPE_ADHOC) + goto dm_checkedcaturbo_exit; if (mac->link_state != MAC80211_LINKED) { rtlpriv->dm.current_turbo_edca = false; return; } - if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { + if (!mac->ht_enable) { /*FIX MERGE */ if (!(edca_be_ul & 0xffff0000)) edca_be_ul |= 0x005e0000; @@ -618,12 +586,10 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) edca_be_dl |= 0x005e0000; } - if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting))) { - + if ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) { cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - if (cur_rxok_cnt > 4 * cur_txok_cnt) { if (!rtlpriv->dm.is_cur_rdlstate || !rtlpriv->dm.current_turbo_edca) { @@ -652,6 +618,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) } } +dm_checkedcaturbo_exit: rtlpriv->dm.is_any_nonbepkts = false; last_txok_cnt = rtlpriv->stats.txbytesunicast; last_rxok_cnt = rtlpriv->stats.rxbytesunicast; @@ -666,14 +633,14 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 thermalvalue, delta, delta_lck, delta_iqk; long ele_a, ele_d, temp_cck, val_x, value32; - long val_y, ele_c = 0; - u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0; + long val_y, ele_c; + u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old; int i; bool is2t = IS_92C_SERIAL(rtlhal->version); u8 txpwr_level[2] = {0, 0}; u8 ofdm_min_index = 6, rf; - rtlpriv->dm.txpower_trackinginit = true; + rtlpriv->dm.txpower_trackingInit = true; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n")); @@ -716,6 +683,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw for (i = 0; i < OFDM_TABLE_LENGTH; i++) { if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[1] = (u8) i; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -1094,7 +1062,7 @@ static void rtl92c_dm_initialize_txpower_tracking_thermalmeter( struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackinginit = false; + rtlpriv->dm.txpower_trackingInit = false; RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("pMgntInfo->txpower_tracking = %d\n", @@ -1164,7 +1132,6 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rate_adaptive *p_ra = &(rtlpriv->ra); u32 low_rssithresh_for_ra, high_rssithresh_for_ra; - struct ieee80211_sta *sta = NULL; if (is_hal_stop(rtlhal)) { RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, @@ -1178,8 +1145,8 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) return; } - if (mac->link_state == MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { + if (mac->link_state == MAC80211_LINKED) { + switch (p_ra->pre_ratr_state) { case DM_RATR_STA_HIGH: high_rssithresh_for_ra = 50; @@ -1218,13 +1185,10 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) ("PreState = %d, CurState = %d\n", p_ra->pre_ratr_state, p_ra->ratr_state)); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + rtlpriv->cfg->ops->update_rate_mask(hw, p_ra->ratr_state); p_ra->pre_ratr_state = p_ra->ratr_state; - rcu_read_unlock(); } } } @@ -1238,6 +1202,51 @@ static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) dm_pstable.rssi_val_min = 0; } +static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (dm_pstable.rssi_val_min != 0) { + if (dm_pstable.pre_ccastate == CCA_2R) { + if (dm_pstable.rssi_val_min >= 35) + dm_pstable.cur_ccasate = CCA_1R; + else + dm_pstable.cur_ccasate = CCA_2R; + } else { + if (dm_pstable.rssi_val_min <= 30) + dm_pstable.cur_ccasate = CCA_2R; + else + dm_pstable.cur_ccasate = CCA_1R; + } + } else { + dm_pstable.cur_ccasate = CCA_MAX; + } + + if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) { + if (dm_pstable.cur_ccasate == CCA_1R) { + if (get_rf_type(rtlphy) == RF_2T2R) { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x13); + rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20); + } else { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x23); + rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c); + } + } else { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, + 0x33); + rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63); + } + dm_pstable.pre_ccastate = dm_pstable.cur_ccasate; + } + + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n", + (dm_pstable.cur_ccasate == + 0) ? "1RCCA" : "2RCCA")); +} + void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) { static u8 initialize; @@ -1343,9 +1352,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) } if (IS_92C_SERIAL(rtlhal->version)) - ;/* rtl92c_dm_1r_cca(hw); */ - else - rtl92c_dm_rf_saving(hw, false); + rtl92c_dm_1r_cca(hw); } void rtl92c_dm_init(struct ieee80211_hw *hw) @@ -1362,84 +1369,6 @@ void rtl92c_dm_init(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_dm_init); -void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undecorated_smoothed_pwdb; - - if (!rtlpriv->dm.dynamic_txpower_enable) - return; - - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - ("Not connected to any\n")); - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undecorated_smoothed_pwdb = - rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("AP Client PWDB = 0x%lx\n", - undecorated_smoothed_pwdb)); - } else { - undecorated_smoothed_pwdb = - rtlpriv->dm.undecorated_smoothed_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("STA Default Port PWDB = 0x%lx\n", - undecorated_smoothed_pwdb)); - } - } else { - undecorated_smoothed_pwdb = - rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("AP Ext Port PWDB = 0x%lx\n", - undecorated_smoothed_pwdb)); - } - - if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n")); - } else if ((undecorated_smoothed_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && - (undecorated_smoothed_pwdb >= - TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n")); - } else if (undecorated_smoothed_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("TXHIGHPWRLEVEL_NORMAL\n")); - } - - if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel)); - rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); - } - - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} - void rtl92c_dm_watchdog(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1459,321 +1388,11 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) rtl92c_dm_dig(hw); rtl92c_dm_false_alarm_counter_statistics(hw); rtl92c_dm_dynamic_bb_powersaving(hw); - rtl92c_dm_dynamic_txpower(hw); + rtlpriv->cfg->ops->dm_dynamic_txpower(hw); rtl92c_dm_check_txpower_tracking(hw); rtl92c_dm_refresh_rate_adaptive_mask(hw); - rtl92c_dm_bt_coexist(hw); rtl92c_dm_check_edca_turbo(hw); - } -} -EXPORT_SYMBOL(rtl92c_dm_watchdog); - -u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - long undecorated_smoothed_pwdb; - u8 curr_bt_rssi_state = 0x00; - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - undecorated_smoothed_pwdb = - GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); - } else { - if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0) - undecorated_smoothed_pwdb = 100; - else - undecorated_smoothed_pwdb = - rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; - } - - /* Check RSSI to determine HighPower/NormalPower state for - * BT coexistence. */ - if (undecorated_smoothed_pwdb >= 67) - curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); - else if (undecorated_smoothed_pwdb < 62) - curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; - - /* Check RSSI to determine AMPDU setting for BT coexistence. */ - if (undecorated_smoothed_pwdb >= 40) - curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); - else if (undecorated_smoothed_pwdb <= 32) - curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; - - /* Marked RSSI state. It will be used to determine BT coexistence - * setting later. */ - if (undecorated_smoothed_pwdb < 35) - curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; - else - curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); - - /* Set Tx Power according to BT status. */ - if (undecorated_smoothed_pwdb >= 30) - curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; - else if (undecorated_smoothed_pwdb < 25) - curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); - - /* Check BT state related to BT_Idle in B/G mode. */ - if (undecorated_smoothed_pwdb < 15) - curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; - else - curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); - - if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) { - rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state; - return true; - } else { - return false; - } -} -EXPORT_SYMBOL(rtl92c_bt_rssi_state_change); - -static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - u32 polling, ratio_tx, ratio_pri; - u32 bt_tx, bt_pri; - u8 bt_state; - u8 cur_service_type; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) - return false; - - bt_state = rtl_read_byte(rtlpriv, 0x4fd); - bt_tx = rtl_read_dword(rtlpriv, 0x488); - bt_tx = bt_tx & 0x00ffffff; - bt_pri = rtl_read_dword(rtlpriv, 0x48c); - bt_pri = bt_pri & 0x00ffffff; - polling = rtl_read_dword(rtlpriv, 0x490); - - if (bt_tx == 0xffffffff && bt_pri == 0xffffffff && - polling == 0xffffffff && bt_state == 0xff) - return false; - - bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1); - if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) { - rtlpcipriv->bt_coexist.bt_cur_state = bt_state; - - if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) { - rtlpcipriv->bt_coexist.bt_service = BT_IDLE; - - bt_state = bt_state | - ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - BIT_OFFSET_LEN_MASK_32(2, 1); - rtl_write_byte(rtlpriv, 0x4fd, bt_state); - } - return true; - } - - ratio_tx = bt_tx * 1000 / polling; - ratio_pri = bt_pri * 1000 / polling; - rtlpcipriv->bt_coexist.ratio_tx = ratio_tx; - rtlpcipriv->bt_coexist.ratio_pri = ratio_pri; - - if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) { - - if ((ratio_tx < 30) && (ratio_pri < 30)) - cur_service_type = BT_IDLE; - else if ((ratio_pri > 110) && (ratio_pri < 250)) - cur_service_type = BT_SCO; - else if ((ratio_tx >= 200) && (ratio_pri >= 200)) - cur_service_type = BT_BUSY; - else if ((ratio_tx >= 350) && (ratio_tx < 500)) - cur_service_type = BT_OTHERBUSY; - else if (ratio_tx >= 500) - cur_service_type = BT_PAN; - else - cur_service_type = BT_OTHER_ACTION; - - if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) { - rtlpcipriv->bt_coexist.bt_service = cur_service_type; - bt_state = bt_state | - ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ? - 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); - - /* Add interrupt migration when bt is not ini - * idle state (no traffic). */ - if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { - rtl_write_word(rtlpriv, 0x504, 0x0ccc); - rtl_write_byte(rtlpriv, 0x506, 0x54); - rtl_write_byte(rtlpriv, 0x507, 0x54); - } else { - rtl_write_byte(rtlpriv, 0x506, 0x00); - rtl_write_byte(rtlpriv, 0x507, 0x00); - } - - rtl_write_byte(rtlpriv, 0x4fd, bt_state); - return true; - } - } - - return false; - -} - -static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - static bool media_connect; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { - media_connect = false; - } else { - if (!media_connect) { - media_connect = true; - return true; - } - media_connect = true; - } - - return false; -} - -static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - - if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b; - } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f; - } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) { - if (rtlpcipriv->bt_coexist.ratio_tx > 160) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f; - } else { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b; - } - } else { - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - } - - if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) && - (rtlpriv->mac80211.mode == WIRELESS_MODE_G || - (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) && - (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_BG_EDCA_LOW)) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b; - } -} - -static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - - /* Only enable HW BT coexist when BT in "Busy" state. */ - if (rtlpriv->mac80211.vendor == PEER_CISCO && - rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - } else { - if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) && - (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_NORMAL_POWER)) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - } else if ((rtlpcipriv->bt_coexist.bt_service == - BT_OTHER_ACTION) && (rtlpriv->mac80211.mode < - WIRELESS_MODE_N_24G) && - (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_SPECIAL_LOW)) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); - } else { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); - } - } - - if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100); - else - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0); - - if (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_NORMAL_POWER) { - rtl92c_bt_set_normal(hw); - } else { - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - } - - if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { - rtlpriv->cfg->ops->set_rfreg(hw, - RF90_PATH_A, - 0x1e, - 0xf0, 0xf); - } else { - rtlpriv->cfg->ops->set_rfreg(hw, - RF90_PATH_A, 0x1e, 0xf0, - rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); - } - - if (!rtlpriv->dm.dynamic_txpower_enable) { - if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { - if (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_TXPOWER_LOW) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_BT2; - } else { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_BT1; - } - } else { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_NORMAL; - } - rtl92c_phy_set_txpower_level(hw, - rtlpriv->phy.current_channel); - } -} - -static void rtl92c_check_bt_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - if (rtlpcipriv->bt_coexist.bt_cur_state) { - if (rtlpcipriv->bt_coexist.bt_ant_isolation) - rtl92c_bt_ant_isolation(hw); - } else { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); - rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, - rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); - - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - } -} - -void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - bool wifi_connect_change; - bool bt_state_change; - bool rssi_state_change; - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { - - wifi_connect_change = rtl92c_bt_wifi_connect_change(hw); - bt_state_change = rtl92c_bt_state_change(hw); - rssi_state_change = rtl92c_bt_rssi_state_change(hw); - - if (wifi_connect_change || bt_state_change || rssi_state_change) - rtl92c_check_bt_change(hw); } } -EXPORT_SYMBOL(rtl92c_dm_bt_coexist); +EXPORT_SYMBOL(rtl92c_dm_watchdog); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h index b9736d3e9a39..b9cbb0a3c03f 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h @@ -200,7 +200,5 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); -void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); -void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 50303e1adff1..28a6ce3bc239 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -171,6 +171,7 @@ static void _rtl92c_write_fw(struct ieee80211_hw *hw, static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; u32 counter = 0; u32 value32; @@ -183,7 +184,7 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("chksum report faill ! REG_MCUFWDL:0x%08x .\n", value32)); - return -EIO; + goto exit; } RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, @@ -203,7 +204,8 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) ("Polling FW ready success!!" " REG_MCUFWDL:0x%08x .\n", value32)); - return 0; + err = 0; + goto exit; } mdelay(FW_8192C_POLLING_DELAY); @@ -212,7 +214,9 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32)); - return -EIO; + +exit: + return err; } int rtl92c_download_fw(struct ieee80211_hw *hw) @@ -222,16 +226,32 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) struct rtl92c_firmware_header *pfwheader; u8 *pfwdata; u32 fwsize; + int err; enum version_8192c version = rtlhal->version; + const struct firmware *firmware; - printk(KERN_INFO "rtl8192c: Loading firmware file %s\n", + printk(KERN_INFO "rtl8192cu: Loading firmware file %s\n", rtlpriv->cfg->fw_name); - if (!rtlhal->pfirmware) + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); + if (err) { + printk(KERN_ERR "rtl8192cu: Firmware loading failed\n"); + return 1; + } + + if (firmware->size > 0x4000) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); return 1; + } + + memcpy(rtlhal->pfirmware, firmware->data, firmware->size); + fwsize = firmware->size; + release_firmware(firmware); pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware; - fwsize = rtlhal->fwsize; if (IS_FW_HEADER_EXIST(pfwheader)) { RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, @@ -247,7 +267,8 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) _rtl92c_write_fw(hw, version, pfwdata, fwsize); _rtl92c_enable_fw_download(hw, false); - if (_rtl92c_fw_free_to_go(hw)) { + err = _rtl92c_fw_free_to_go(hw); + if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Firmware is not ready to run!\n")); } else { @@ -279,9 +300,10 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 boxnum; - u16 box_reg = 0, box_extreg = 0; + u16 box_reg, box_extreg; u8 u1b_tmp; bool isfw_read = false; + u8 buf_index = 0; bool bwrite_sucess = false; u8 wait_h2c_limmit = 100; u8 wait_writeh2c_limmit = 100; @@ -392,7 +414,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 1: boxcontent[0] &= ~(BIT(7)); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer, 1); + p_cmdbuffer + buf_index, 1); for (idx = 0; idx < 4; idx++) { rtl_write_byte(rtlpriv, box_reg + idx, @@ -402,7 +424,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 2: boxcontent[0] &= ~(BIT(7)); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer, 2); + p_cmdbuffer + buf_index, 2); for (idx = 0; idx < 4; idx++) { rtl_write_byte(rtlpriv, box_reg + idx, @@ -412,7 +434,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 3: boxcontent[0] &= ~(BIT(7)); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer, 3); + p_cmdbuffer + buf_index, 3); for (idx = 0; idx < 4; idx++) { rtl_write_byte(rtlpriv, box_reg + idx, @@ -422,9 +444,9 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 4: boxcontent[0] |= (BIT(7)); memcpy((u8 *) (boxextcontent), - p_cmdbuffer, 2); + p_cmdbuffer + buf_index, 2); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + 2, 2); + p_cmdbuffer + buf_index + 2, 2); for (idx = 0; idx < 2; idx++) { rtl_write_byte(rtlpriv, box_extreg + idx, @@ -439,9 +461,9 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, case 5: boxcontent[0] |= (BIT(7)); memcpy((u8 *) (boxextcontent), - p_cmdbuffer, 2); + p_cmdbuffer + buf_index, 2); memcpy((u8 *) (boxcontent) + 1, - p_cmdbuffer + 2, 3); + p_cmdbuffer + buf_index + 2, 3); for (idx = 0; idx < 2; idx++) { rtl_write_byte(rtlpriv, box_extreg + idx, @@ -539,39 +561,6 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) } EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd); -static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - u8 own; - unsigned long flags; - struct sk_buff *pskb = NULL; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - - pskb = __skb_dequeue(&ring->queue); - if (pskb) - kfree_skb(pskb); - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - - pdesc = &ring->desc[0]; - own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); - - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); - - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - - return true; -} - #define BEACON_PG 0 /*->1*/ #define PSPOLL_PG 2 #define NULL_PG 3 @@ -689,7 +678,7 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -698,12 +687,12 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) u32 totalpacketlen; bool rtstatus; u8 u1RsvdPageLoc[3] = {0}; - bool dlok = false; + bool b_dlok = false; u8 *beacon; - u8 *pspoll; + u8 *p_pspoll; u8 *nullfunc; - u8 *probersp; + u8 *p_probersp; /*--------------------------------------------------------- (1) beacon ---------------------------------------------------------*/ @@ -714,10 +703,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) /*------------------------------------------------------- (2) ps-poll --------------------------------------------------------*/ - pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); - SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); @@ -734,10 +723,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) /*--------------------------------------------------------- (4) probe response ----------------------------------------------------------*/ - probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(probersp, mac->bssid); + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); @@ -755,12 +744,12 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, totalpacketlen); - rtstatus = _rtl92c_cmd_send_packet(hw, skb); + rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb); if (rtstatus) - dlok = true; + b_dlok = true; - if (dlok) { + if (b_dlok) { RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Set RSVD page location to Fw.\n")); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h index 3d5823c12621..3db33bd14666 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h @@ -27,8 +27,8 @@ * *****************************************************************************/ -#ifndef __RTL92C__FW__COMMON__H__ -#define __RTL92C__FW__COMMON__H__ +#ifndef __RTL92C__FW__H__ +#define __RTL92C__FW__H__ #define FW_8192C_SIZE 0x3000 #define FW_8192C_START_ADDRESS 0x1000 diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index c5424cad43cb..a70228278398 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -78,29 +78,27 @@ void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," " data(%#x)\n", regaddr, bitmask, data)); - } EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) + enum radio_path rfpath, u32 offset) { RT_ASSERT(false, ("deprecated!\n")); return 0; - } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) + enum radio_path rfpath, u32 offset, + u32 data) { RT_ASSERT(false, ("deprecated!\n")); } EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) + enum radio_path rfpath, u32 offset) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -151,8 +149,8 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) + enum radio_path rfpath, u32 offset, + u32 data) { u32 data_and_addr; u32 newoffset; @@ -199,7 +197,6 @@ static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw) rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); } - bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -244,14 +241,13 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); - return true; } EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) + u32 regaddr, u32 bitmask, + u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -321,48 +317,61 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, } if (regaddr == RTXAGC_B_RATE54_24) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9])); } + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14])); } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15])); } + if (regaddr == RTXAGC_B_MCS03_MCS00) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10])); } + if (regaddr == RTXAGC_B_MCS07_MCS04) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11])); } + if (regaddr == RTXAGC_B_MCS11_MCS08) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", rtlphy->pwrgroup_cnt, rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12])); } + if (regaddr == RTXAGC_B_MCS15_MCS12) { rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", rtlphy->pwrgroup_cnt, @@ -574,7 +583,6 @@ static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw, rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; - } void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) @@ -603,6 +611,7 @@ bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 idx; u8 rf_path; + u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_B, power_indbm); @@ -630,6 +639,11 @@ bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) } EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval) +{ +} +EXPORT_SYMBOL(rtl92c_phy_set_beacon_hw_reg); + u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, enum wireless_mode wirelessmode, long power_indbm) @@ -727,9 +741,9 @@ void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, if (rtlphy->set_bwmode_inprogress) return; rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtlphy->set_bwmode_inprogress = false; - } else { + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) + rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); + else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("FALSE driver sleep or unload\n")); rtlphy->set_bwmode_inprogress = false; @@ -759,9 +773,8 @@ void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw) mdelay(delay); else continue; - } else { + } else rtlphy->sw_chnl_inprogress = false; - } break; } while (true); RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); @@ -798,32 +811,9 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl92c_phy_sw_chnl); -static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - -bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) +static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -927,6 +917,29 @@ bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, return false; } +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) { return true; @@ -989,13 +1002,13 @@ static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw) reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); - if (!(reg_eac & BIT(31)) && (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) result |= 0x01; else return result; + if (!(reg_eac & BIT(30)) && (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) @@ -1010,9 +1023,9 @@ static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, u32 oldval_0, x, tx0_a, reg; long y, tx0_c; - if (final_candidate == 0xFF) { + if (final_candidate == 0xFF) return; - } else if (iqk_ok) { + else if (iqk_ok) { oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; x = result[final_candidate][0]; @@ -1050,9 +1063,9 @@ static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, u32 oldval_1, x, tx1_a, reg; long y, tx1_c; - if (final_candidate == 0xFF) { + if (final_candidate == 0xFF) return; - } else if (iqk_ok) { + else if (iqk_ok) { oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; x = result[final_candidate][4]; @@ -1269,7 +1282,6 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, RFPGA0_XA_HSSIPARAMETER1, BIT(8)); } - if (!rtlphy->rfpi_enable) _rtl92c_phy_pi_mode_switch(hw, true); if (t == 0) { @@ -1305,10 +1317,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, 0x3FF0000) >> 16; break; } else if (i == (retrycount - 1) && patha_ok == 0x01) - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & 0x3FF0000) >> - 16; + 16; result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; @@ -1364,7 +1375,8 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta, bool is2t) { -#if 0 /* This routine is deliberately dummied out for later fixes */ + /* This routine is deliberately dummied out for later fixes */ +#if 0 struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); @@ -1422,7 +1434,7 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x04db25a4, 0x0b1b25a4 }; - const u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; + u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 }; @@ -1451,15 +1463,13 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x00050006 }; - u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; + const u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; long bb_offset, delta_v, delta_offset; if (!is2t) pathbound = 1; - return; - for (index = 0; index < PATH_NUM; index++) { apk_offset[index] = apk_normal_offset[index]; apk_value[index] = apk_normal_value[index]; @@ -1720,7 +1730,8 @@ static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, 0x08)); } - rtlphy->b_apk_done = true; + + rtlphy->apk_done = true; #endif } @@ -1747,7 +1758,6 @@ static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); } - } #undef IQK_ADDA_REG_NUM diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h index 9a264c0d6127..53ffb0981586 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h @@ -27,8 +27,8 @@ * *****************************************************************************/ -#ifndef __RTL92C_PHY_COMMON_H__ -#define __RTL92C_PHY_COMMON_H__ +#ifndef __RTL92C_PHY_H__ +#define __RTL92C_PHY_H__ #define MAX_PRECMD_CNT 16 #define MAX_RFDEPENDCMD_CNT 16 @@ -39,7 +39,6 @@ #define RT_CANNOT_IO(hw) false #define HIGHPOWER_RADIOA_ARRAYLEN 22 -#define IQK_ADDA_REG_NUM 16 #define MAX_TOLERANCE 5 #define IQK_DELAY_TIME 1 @@ -57,7 +56,6 @@ #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 -#define IQK_DELAY_TIME 1 #define RF90_PATH_MAX 2 #define CT_OFFSET_MAC_ADDR 0X16 @@ -79,7 +77,6 @@ #define RTL92C_MAX_PATH_NUM 2 #define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 - enum swchnlcmd_id { CMDID_END, CMDID_SET_TXPOWEROWER_LEVEL, @@ -187,41 +184,45 @@ struct tx_power_struct { u32 mcs_original_offset[4][16]; }; -u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, +extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); -u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); -bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, enum radio_path rfpath); -void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, +extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm); -void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, +extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); -void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, +extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, +extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); -bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, +extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state); void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); void rtl92c_phy_set_io(struct ieee80211_hw *hw); @@ -234,25 +235,12 @@ u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, enum wireless_mode wirelessmode, long power_indbm); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); -void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); -bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay); -u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw); -u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data); -bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, u32 para1, + u32 para2, u32 msdelay); +static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 35ff7df41a1d..2f577c8828fc 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -121,6 +121,19 @@ #define CHIP_92C 0x01 #define CHIP_88C 0x00 +/* Add vendor information into chip version definition. + * Add UMC B-Cut and RTL8723 chip info definition. + * + * BIT 7 Reserved + * BIT 6 UMC BCut + * BIT 5 Manufacturer(TSMC/UMC) + * BIT 4 TEST/NORMAL + * BIT 3 8723 Version + * BIT 2 8723? + * BIT 1 1T2R? + * BIT 0 88C/92C +*/ + enum version_8192c { VERSION_A_CHIP_92C = 0x01, VERSION_A_CHIP_88C = 0x00, @@ -267,6 +280,20 @@ struct h2c_cmd_8192c { u8 *p_cmdbuffer; }; +static inline u8 _rtl92c_get_chnl_group(u8 chnl) +{ + u8 group = 0; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + + return group; +} + /* NOTE: reference to rtl8192c_rates struct */ static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, u8 desc_rate, bool first_ampdu) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c index 2df33e53e15a..7d76504df4d1 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c @@ -29,12 +29,10 @@ #include "../wifi.h" #include "../base.h" -#include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" #include "dm.h" -#include "../rtl8192c/fw_common.h" void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h index 07dd9552e82f..36302ebae4a3 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h @@ -192,7 +192,6 @@ void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); -void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 4a56138eb33c..05477f465a75 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -30,14 +30,12 @@ #include "../wifi.h" #include "../efuse.h" #include "../base.h" -#include "../regd.h" #include "../cam.h" #include "../ps.h" #include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" -#include "../rtl8192c/fw_common.h" #include "dm.h" #include "led.h" #include "hw.h" @@ -139,6 +137,15 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } + case HW_VAR_MGT_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); + break; + case HW_VAR_CTRL_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); + break; + case HW_VAR_DATA_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); + break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case not process\n")); @@ -149,7 +156,6 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -172,7 +178,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rate_cfg |= 0x01; rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); rtl_write_byte(rtlpriv, REG_RRSR + 1, - (rate_cfg >> 8) & 0xff); + (rate_cfg >> 8)&0xff); while (rate_cfg > 0x1) { rate_cfg = (rate_cfg >> 1); rate_index++; @@ -270,19 +276,13 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; - u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; + u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; u8 factor_toset; u8 *p_regtoset = NULL; u8 index = 0; - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == - BT_CSR_BC4)) - p_regtoset = regtoset_bt; - else - p_regtoset = regtoset_normal; + p_regtoset = regtoset_normal; factor_toset = *((u8 *) val); if (factor_toset <= 3) { @@ -317,7 +317,45 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } case HW_VAR_AC_PARAM:{ u8 e_aci = *((u8 *) val); - rtl92c_dm_init_edca_turbo(hw); + u32 u4b_ac_param; + u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); + u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); + u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); + + u4b_ac_param = (u32) mac->ac[e_aci].aifs; + u4b_ac_param |= ((u32)cw_min + & 0xF) << AC_PARAM_ECW_MIN_OFFSET; + u4b_ac_param |= ((u32)cw_max & + 0xF) << AC_PARAM_ECW_MAX_OFFSET; + u4b_ac_param |= (u32)tx_op << AC_PARAM_TXOP_OFFSET; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + ("queue:%x, ac_param:%x\n", e_aci, + u4b_ac_param)); + + switch (e_aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, + u4b_ac_param); + break; + case AC0_BE: + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, + u4b_ac_param); + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, + u4b_ac_param); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, + u4b_ac_param); + break; + default: + RT_ASSERT(false, + ("SetHwReg8185(): invalid aci: %d !\n", + e_aci)); + break; + } if (rtlpci->acm_method != eAcmWay2_SW) rtlpriv->cfg->ops->set_hw_reg(hw, @@ -488,6 +526,9 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_CORRECT_TSF:{ u8 btype_ibss = ((u8 *) (val))[0]; + /*btype_ibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? + 1 : 0;*/ + if (btype_ibss == true) _rtl92ce_stop_tx_beacon(hw); @@ -496,7 +537,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_dword(rtlpriv, REG_TSFTR, (u32) (mac->tsf & 0xffffffff)); rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32) ((mac->tsf >> 32) & 0xffffffff)); + (u32) ((mac->tsf >> 32)&0xffffffff)); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); @@ -506,6 +547,15 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } + case HW_VAR_MGT_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *) val); + break; + case HW_VAR_CTRL_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *) val); + break; + case HW_VAR_DATA_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *) val); + break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " "not process\n")); @@ -629,12 +679,12 @@ static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) rtl92ce_sw_led_on(hw, pLed0); else rtl92ce_sw_led_off(hw, pLed0); + } static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -643,22 +693,9 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) u16 retry; rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - if (rtlpcipriv->bt_coexist.bt_coexistence) { - u32 value32; - value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); - value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); - rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); - } rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); - if (rtlpcipriv->bt_coexist.bt_coexistence) { - u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); - - u4b_tmp &= (~0x00024800); - rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); - } - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); udelay(2); @@ -689,11 +726,6 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); udelay(2); - if (rtlpcipriv->bt_coexist.bt_coexistence) { - bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd; - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp); - } - rtl_write_word(rtlpriv, REG_CR, 0x2ff); if (_rtl92ce_llt_table_init(hw) == false) @@ -761,7 +793,6 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); u8 reg_bw_opmode; u32 reg_ratr, reg_prsr; @@ -793,11 +824,7 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); - else - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); @@ -813,20 +840,11 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); - } else { - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - } + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); - else - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); @@ -930,8 +948,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) } rtlhal->last_hmeboxnum = 0; - rtl92c_phy_mac_config(hw); - rtl92c_phy_bb_config(hw); + rtl92ce_phy_mac_config(hw); + rtl92ce_phy_bb_config(hw); rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; rtl92c_phy_rf_config(hw); rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, @@ -944,20 +962,15 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) _rtl92ce_hw_configure(hw); rtl_cam_reset_all_entry(hw); rtl92ce_enable_hw_security_config(hw); - ppsc->rfpwr_state = ERFON; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); _rtl92ce_enable_aspm_back_door(hw); rtlpriv->intf_ops->enable_aspm(hw); - - rtl8192ce_bt_hw_init(hw); - if (ppsc->rfpwr_state == ERFON) { rtl92c_phy_set_rfpath_switch(hw, 1); - if (iqk_initialized) { + if (iqk_initialized) rtl92c_phy_iq_calibrate(hw, true); - } else { + else { rtl92c_phy_iq_calibrate(hw, false); iqk_initialized = true; } @@ -1115,62 +1128,75 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, return 0; } -void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +static void _rtl92ce_set_check_bssid(struct ieee80211_hw *hw, + enum nl80211_iftype type) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); + u8 filterout_non_associated_bssid = false; - if (rtlpriv->psc.rfpwr_state != ERFON) - return; + switch (type) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + filterout_non_associated_bssid = true; + break; + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_AP: + default: + break; + } - if (check_bssid == true) { + if (filterout_non_associated_bssid == true) { reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (®_rcr)); _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (check_bssid == false) { + } else if (filterout_non_associated_bssid == false) { reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (®_rcr)); } - } int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) { - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (_rtl92ce_set_media_status(hw, type)) return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl92ce_set_check_bssid(hw, true); - } else { - rtl92ce_set_check_bssid(hw, false); - } - + _rtl92ce_set_check_bssid(hw, type); return 0; } -/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u32 u4b_ac_param; + u16 cw_min = le16_to_cpu(mac->ac[aci].cw_min); + u16 cw_max = le16_to_cpu(mac->ac[aci].cw_max); + u16 tx_op = le16_to_cpu(mac->ac[aci].tx_op); + rtl92c_dm_init_edca_turbo(hw); + u4b_ac_param = (u32) mac->ac[aci].aifs; + u4b_ac_param |= (u32) ((cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET); + u4b_ac_param |= (u32) ((cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET); + u4b_ac_param |= (u32) (tx_op << AC_PARAM_TXOP_OFFSET); + RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG, + ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n", + aci, u4b_ac_param, mac->ac[aci].aifs, cw_min, + cw_max, tx_op)); switch (aci) { case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param); break; case AC0_BE: - /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); break; case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param); break; case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param); break; default: RT_ASSERT(false, ("invalid aci: %d !\n", aci)); @@ -1201,10 +1227,8 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 u1b_tmp; - u32 u4b_tmp; rtlpriv->intf_ops->enable_aspm(hw); rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); @@ -1219,27 +1243,13 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) { - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 | - (u1b_tmp << 8)); - } else { - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | - (u1b_tmp << 8)); - } + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | + (u1b_tmp << 8)); rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); - if (rtlpcipriv->bt_coexist.bt_coexistence) { - u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); - u4b_tmp |= 0x03824800; - rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); - } else { - rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); - } - + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); } @@ -1317,7 +1327,6 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); - if (add_msr) rtlpci->irq_mask[0] |= add_msr; if (rm_msr) @@ -1573,7 +1582,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) ("RTL819X Not boot from eeprom, check it !!")); } - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"), hwinfo, HWSET_MAX_SIZE); eeprom_id = *((u16 *)&hwinfo[0]); @@ -1601,10 +1610,6 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) rtlefuse->autoload_failflag, hwinfo); - rtl8192ce_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, - hwinfo); - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; rtlefuse->txpwr_fromeprom = true; @@ -1613,9 +1618,6 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid)); - /* set channel paln to world wide 13 */ - rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; - if (rtlhal->oem_id == RT_CID_DEFAULT) { switch (rtlefuse->eeprom_oemid) { case EEPROM_CID_DEFAULT: @@ -1699,36 +1701,30 @@ void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw) } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); } + _rtl92ce_hal_customized_behavior(hw); } -static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) +void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; + + u32 ratr_value = (u32) mac->basic_rates; + u8 *mcsrate = mac->mcs; u8 ratr_index = 0; u8 nmode = mac->ht_enable; - u8 mimo_ps = IEEE80211_SMPS_OFF; + u8 mimo_ps = 1; u16 shortgi_rate; u32 tmp_ratr_value; u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; + u8 curshortgi_40mhz = mac->sgi_40; + u8 curshortgi_20mhz = mac->sgi_20; enum wireless_mode wirelessmode = mac->mode; - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); + ratr_value |= ((*(u16 *) (mcsrate))) << 12; + switch (wirelessmode) { case WIRELESS_MODE_B: if (ratr_value & 0x0000000c) @@ -1742,7 +1738,7 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, case WIRELESS_MODE_N_24G: case WIRELESS_MODE_N_5G: nmode = 1; - if (mimo_ps == IEEE80211_SMPS_STATIC) { + if (mimo_ps == 0) { ratr_value &= 0x0007F005; } else { u32 ratr_mask; @@ -1765,19 +1761,10 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, break; } - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && - (rtlpcipriv->bt_coexist.bt_cur_state) && - (rtlpcipriv->bt_coexist.bt_ant_isolation) && - ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) || - (rtlpcipriv->bt_coexist.bt_service == BT_BUSY))) - ratr_value &= 0x0fffcfc0; - else - ratr_value &= 0x0FFFFFFF; + ratr_value &= 0x0FFFFFFF; - if (nmode && ((curtxbw_40mhz && - curshortgi_40mhz) || (!curtxbw_40mhz && - curshortgi_20mhz))) { + if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { ratr_value |= 0x10000000; tmp_ratr_value = (ratr_value >> 12); @@ -1797,42 +1784,24 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0))); } -static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) +void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; + u32 ratr_bitmap = (u32) mac->basic_rates; + u8 *p_mcsrate = mac->mcs; u8 ratr_index; - u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = mac->sgi_40; + u8 curshortgi_20mhz = mac->sgi_20; + enum wireless_mode wirelessmode = mac->mode; bool shortgi = false; u8 rate_mask[5]; u8 macid = 0; - u8 mimo_ps = IEEE80211_SMPS_OFF; - - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); + u8 mimops = 1; + + ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12); switch (wirelessmode) { case WIRELESS_MODE_B: ratr_index = RATR_INX_WIRELESS_B; @@ -1859,7 +1828,7 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, case WIRELESS_MODE_N_5G: ratr_index = RATR_INX_WIRELESS_NGB; - if (mimo_ps == IEEE80211_SMPS_STATIC) { + if (mimops == 0) { if (rssi_level == 1) ratr_bitmap &= 0x00070000; else if (rssi_level == 2) @@ -1923,8 +1892,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, } RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("ratr_bitmap :%x\n", ratr_bitmap)); - *(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | - (ratr_index << 28)); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, " "ratr_val:%x, %x:%x:%x:%x:%x\n", @@ -1933,20 +1902,6 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, rate_mask[2], rate_mask[3], rate_mask[4])); rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); - - if (macid != 0) - sta_entry->ratr_index = ratr_index; -} - -void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl92ce_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl92ce_update_hal_rate_table(hw, sta); } void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) @@ -1964,7 +1919,7 @@ void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); } -bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -1974,7 +1929,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) bool actuallyset = false; unsigned long flag; - if (rtlpci->being_init_adapter) + if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) return false; if (ppsc->swrf_processing) @@ -1991,6 +1946,12 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) cur_rfstate = ppsc->rfpwr_state; + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG)&~(BIT(3))); @@ -2015,13 +1976,38 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) } if (actuallyset) { + if (e_rfpowerstate_toset == ERFON) { + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + } + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } else { + + if (e_rfpowerstate_toset == ERFOFF) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + } + + } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + } + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } else { spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); ppsc->rfchange_inprogress = false; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); @@ -2100,31 +2086,15 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, macaddr = cam_const_broad; entry_id = key_index; } else { - if (mac->opmode == NL80211_IFTYPE_AP) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - ("Can not find free hw" - " security cam entry\n")); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - key_index = PAIRWISE_KEYIDX; + entry_id = CAM_PAIRWISE_KEY_POSITION; is_pairwise = true; } } if (rtlpriv->sec.key_len[key_index] == 0) { RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("delete one entry, entry_id is %d\n", - entry_id)); - if (mac->opmode == NL80211_IFTYPE_AP) - rtl_cam_del_entry(hw, p_macaddr); + ("delete one entry\n")); rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); } else { RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, @@ -2176,132 +2146,3 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, } } } - -static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - rtlpcipriv->bt_coexist.bt_coexistence = - rtlpcipriv->bt_coexist.eeprom_bt_coexist; - rtlpcipriv->bt_coexist.bt_ant_num = - rtlpcipriv->bt_coexist.eeprom_bt_ant_num; - rtlpcipriv->bt_coexist.bt_coexist_type = - rtlpcipriv->bt_coexist.eeprom_bt_type; - - if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) - rtlpcipriv->bt_coexist.bt_ant_isolation = - rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation; - else - rtlpcipriv->bt_coexist.bt_ant_isolation = - rtlpcipriv->bt_coexist.reg_bt_iso; - - rtlpcipriv->bt_coexist.bt_radio_shared_type = - rtlpcipriv->bt_coexist.eeprom_bt_radio_shared; - - if (rtlpcipriv->bt_coexist.bt_coexistence) { - - if (rtlpcipriv->bt_coexist.reg_bt_sco == 1) - rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION; - else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2) - rtlpcipriv->bt_coexist.bt_service = BT_SCO; - else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4) - rtlpcipriv->bt_coexist.bt_service = BT_BUSY; - else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5) - rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY; - else - rtlpcipriv->bt_coexist.bt_service = BT_IDLE; - - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - rtlpcipriv->bt_coexist.bt_rssi_state = 0xff; - } -} - -void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - u8 value; - - if (!auto_load_fail) { - rtlpcipriv->bt_coexist.eeprom_bt_coexist = - ((hwinfo[RF_OPTION1] & 0xe0) >> 5); - value = hwinfo[RF_OPTION4]; - rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1); - rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1); - rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = - ((value & 0x10) >> 4); - rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = - ((value & 0x20) >> 5); - } else { - rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; - rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; - rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; - rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0; - rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; - } - - rtl8192ce_bt_var_init(hw); -} - -void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpcipriv->bt_coexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpcipriv->bt_coexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpcipriv->bt_coexist.reg_bt_sco = 0; -} - - -void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - u8 u1_tmp; - - if (rtlpcipriv->bt_coexist.bt_coexistence && - ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || - rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) { - - if (rtlpcipriv->bt_coexist.bt_ant_isolation) - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - - u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & - BIT_OFFSET_LEN_MASK_32(0, 1); - u1_tmp = u1_tmp | - ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ? - 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); - rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); - - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); - - /* Config to 1T1R. */ - if (rtlphy->rf_type == RF_1T1R) { - u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); - u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); - rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); - - u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); - u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); - rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); - } - } -} - -void rtl92ce_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl92ce_resume(struct ieee80211_hw *hw) -{ -} diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h index 07dbe3e340a5..a3dfdb635168 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h @@ -30,18 +30,7 @@ #ifndef __RTL92CE_HW_H__ #define __RTL92CE_HW_H__ -static inline u8 _rtl92c_get_chnl_group(u8 chnl) -{ - u8 group; - - if (chnl < 3) - group = 0; - else if (chnl < 9) - group = 1; - else - group = 2; - return group; -} +#define H2C_RA_MASK 6 void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); @@ -52,27 +41,28 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw); void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); +void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw); +void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); - -void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo); -void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); -void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); -void rtl92ce_suspend(struct ieee80211_hw *hw); -void rtl92ce_resume(struct ieee80211_hw *hw); +bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); +int rtl92c_download_fw(struct ieee80211_hw *hw); +void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); +void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); +bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.c index 9dd1ed7b6422..7b1da8d7508f 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -32,14 +32,6 @@ #include "reg.h" #include "led.h" -static void _rtl92ce_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) { u8 ledcfg; @@ -105,12 +97,13 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) { - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); } -static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, +void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw) +{ +} + +void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); @@ -145,7 +138,7 @@ void rtl92ce_led_control(struct ieee80211_hw *hw, ledaction == LED_CTL_POWER_ON)) { return; } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d.\n", + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", ledaction)); _rtl92ce_sw_led_control(hw, ledaction); } diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.h index 7dfccea2095b..10da3018f4b7 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/led.h @@ -31,8 +31,11 @@ #define __RTL92CE_LED_H__ void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); +void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw); void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); +void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 73ae8a431848..d0541e8c6012 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -38,9 +38,7 @@ #include "dm.h" #include "table.h" -static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); - -u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -75,47 +73,9 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, return readback_value; } -bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool is92c = IS_92C_SERIAL(rtlhal->version); - bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); - - if (is92c) - rtl_write_byte(rtlpriv, 0x14, 0x71); - return rtstatus; -} - -bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u32 regvaldw; - u8 reg_hwparafile = 1; - - _rtl92c_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTn | FEN_BBRSTB); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); - rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); - if (reg_hwparafile == 1) - rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); - return rtstatus; -} - void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -161,7 +121,45 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, bitmask, data, rfpath)); } -static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is92c = IS_92C_SERIAL(rtlhal->version); + bool rtstatus = _rtl92ce_phy_config_mac_with_headerfile(hw); + + if (is92c) + rtl_write_byte(rtlpriv, 0x14, 0x71); + return rtstatus; +} + +bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regvaldw; + u8 reg_hwparafile = 1; + + _rtl92c_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTn | FEN_BBRSTB); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); + rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); + if (reg_hwparafile == 1) + rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + +bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 i; @@ -179,7 +177,7 @@ static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) } bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { int i; u32 *phy_regarray_table; @@ -238,7 +236,7 @@ bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, } bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { struct rtl_priv *rtlpriv = rtl_priv(hw); int i; @@ -276,7 +274,7 @@ bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, return true; } -bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, +bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath) { @@ -366,6 +364,74 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + ("Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz")) + + if (is_hal_stop(rtlhal)) + return; + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + rtl92c_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; @@ -411,36 +477,6 @@ void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } } -static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - u32 u4b_tmp; - u8 delay = 5; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - while (u4b_tmp != 0 && delay > 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - delay--; - } - if (delay == 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - ("Switch RF timeout !!!.\n")); - return; - } - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} - static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { @@ -487,6 +523,33 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, break; } case ERFOFF:{ + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0 || + queue_id == BEACON_QUEUE) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("eRf Off/Sleep: %d times " + "TcbBusyQueue[%d] " + "=%d before doze!\n", (i + 1), + queue_id, + skb_queue_len(&ring->queue))); + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + ("\nERFOFF: %d times " + "TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue))); + break; + } + } if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, ("IPS Set eRf nic disable\n")); @@ -518,7 +581,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, "TcbBusyQueue[%d] =%d before " "doze!\n", (i + 1), queue_id, skb_queue_len(&ring->queue))); - udelay(10); i++; } @@ -537,7 +599,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies))); ppsc->last_sleep_jiffies = jiffies; - _rtl92ce_phy_set_rf_sleep(hw); + _rtl92c_phy_set_rf_sleep(hw); break; } default: @@ -552,11 +614,10 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, return bresult; } -bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, +bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = false; if (rfpwr_state == ppsc->rfpwr_state) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index ad580852cc76..a37267e3fc22 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -39,7 +39,6 @@ #define RT_CANNOT_IO(hw) false #define HIGHPOWER_RADIOA_ARRAYLEN 22 -#define IQK_ADDA_REG_NUM 16 #define MAX_TOLERANCE 5 #define IQK_DELAY_TIME 1 @@ -57,8 +56,6 @@ #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 -#define IQK_DELAY_TIME 1 - #define RF90_PATH_MAX 2 #define CT_OFFSET_MAC_ADDR 0X16 @@ -79,7 +76,7 @@ #define CT_OFFSET_CUSTOMER_ID 0x7F #define RTL92C_MAX_PATH_NUM 2 - +#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 enum swchnlcmd_id { CMDID_END, CMDID_SET_TXPOWEROWER_LEVEL, @@ -187,44 +184,43 @@ struct tx_power_struct { u32 mcs_original_offset[4][16]; }; -bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, +extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); -u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, +extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, enum radio_path rfpath); -void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, +extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm); -void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, +extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, +extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); -void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, +extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); -void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, +extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, @@ -241,6 +237,9 @@ u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); +void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data); void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); @@ -251,11 +250,5 @@ bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); -bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index 598cecc63f41..b0868a613841 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h @@ -72,7 +72,6 @@ #define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ #define REG_MULTI_FUNC_CTRL 0x0068 - #define REG_MCUFWDL 0x0080 #define REG_HMEBOX_EXT_0 0x0088 @@ -543,7 +542,7 @@ #define IMR_OCPINT BIT(1) #define IMR_WLANOFF BIT(0) -#define EFUSE_REAL_CONTENT_LEN 512 +#define HWSET_MAX_SIZE 128 #define EEPROM_DEFAULT_TSSI 0x0 #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 @@ -657,7 +656,6 @@ #define STOPBE BIT(1) #define STOPBK BIT(0) -#define RCR_APPFCS BIT(31) #define RCR_APP_FCS BIT(31) #define RCR_APP_MIC BIT(30) #define RCR_APP_ICV BIT(29) @@ -690,7 +688,6 @@ #define REG_USB_INFO 0xFE17 #define REG_USB_SPECIAL_OPTION 0xFE55 - #define REG_USB_DMA_AGG_TO 0xFE5B #define REG_USB_AGG_TO 0xFE5C #define REG_USB_AGG_TH 0xFE5D @@ -778,6 +775,7 @@ #define BOOT_FROM_EEPROM BIT(4) #define EEPROM_EN BIT(5) +#define EEPROMSEL BOOT_FROM_EEPROM #define AFE_BGEN BIT(0) #define AFE_MBEN BIT(1) @@ -903,7 +901,28 @@ #define BD_PKG_SEL BIT(25) #define BD_HCI_SEL BIT(26) #define TYPE_ID BIT(27) -#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) + +/* REG_GPIO_OUTSTS (For RTL8723 only) */ +#define EFS_HCI_SEL (BIT(0)|BIT(1)) +#define PAD_HCI_SEL (BIT(2)|BIT(3)) +#define HCI_SEL (BIT(4)|BIT(5)) +#define PKG_SEL_HCI BIT(6) +#define FEN_GPS BIT(7) +#define FEN_BT BIT(8) +#define FEN_WL BIT(9) +#define FEN_PCI BIT(10) +#define FEN_USB BIT(11) +#define BTRF_HWPDN_N BIT(12) +#define WLRF_HWPDN_N BIT(13) +#define PDN_BT_N BIT(14) +#define PDN_GPS_N BIT(15) +#define BT_CTL_HWPDN BIT(16) +#define GPS_CTL_HWPDN BIT(17) +#define PPHY_SUSB BIT(20) +#define UPHY_SUSB BIT(21) +#define PCI_SUSEN BIT(22) +#define USB_SUSEN BIT(23) +#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) #define CHIP_VER_RTL_MASK 0xF000 #define CHIP_VER_RTL_SHIFT 12 @@ -1058,7 +1077,6 @@ #define _RARF_RC8(x) (((x) & 0x1F) << 24) #define AC_PARAM_TXOP_OFFSET 16 -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 #define AC_PARAM_ECW_MAX_OFFSET 12 #define AC_PARAM_ECW_MIN_OFFSET 8 #define AC_PARAM_AIFS_OFFSET 0 @@ -1203,12 +1221,34 @@ #define EPROM_CMD_CONFIG 0x3 #define EPROM_CMD_LOAD 1 -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - -#define WL_HWPDN_EN BIT(0) +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE #define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) +/* REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ +/* Enable GPIO[9] as WiFi HW PDn source */ +#define WL_HWPDN_EN BIT(0) +/* WiFi HW PDn polarity control */ +#define WL_HWPDN_SL BIT(1) +/* WiFi function enable */ +#define WL_FUNC_EN BIT(2) +/* Enable GPIO[9] as WiFi RF HW PDn source */ +#define WL_HWROF_EN BIT(3) +/* Enable GPIO[11] as BT HW PDn source */ +#define BT_HWPDN_EN BIT(16) +/* BT HW PDn polarity control */ +#define BT_HWPDN_SL BIT(17) +/* BT function enable */ +#define BT_FUNC_EN BIT(18) +/* Enable GPIO[11] as BT/GPS RF HW PDn source */ +#define BT_HWROF_EN BIT(19) +/* Enable GPIO[10] as GPS HW PDn source */ +#define GPS_HWPDN_EN BIT(20) +/* GPS HW PDn polarity control */ +#define GPS_HWPDN_SL BIT(21) +/* GPS function enable */ +#define GPS_FUNC_EN BIT(22) + #define RPMAC_RESET 0x100 #define RPMAC_TXSTART 0x104 #define RPMAC_TXLEGACYSIG 0x108 diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c index 90d0f2cf3b27..669b1168dbec 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -34,9 +34,9 @@ #include "rf.h" #include "dm.h" -static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); +static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); -void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -62,7 +62,7 @@ void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) } void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) + u8 *ppowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -128,7 +128,8 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tmpval = tx_agc[RF90_PATH_A] >> 8; - tmpval = tmpval & 0xff00ffff; + if (mac->mode == WIRELESS_MODE_B) + tmpval = tmpval & 0xff00ffff; rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); @@ -201,7 +202,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4]; + u8 i, chnlgroup, pwr_diff_limit[4]; u32 writeVal, customer_limit, rf; for (rf = 0; rf < 2; rf++) { @@ -439,17 +440,16 @@ bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw) else rtlphy->num_total_rfpath = 2; - return _rtl92ce_phy_rf6052_config_parafile(hw); - + return _rtl92c_phy_rf6052_config_parafile(hw); } -static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 u4_regvalue = 0; + u32 u4_regvalue; u8 rfpath; - bool rtstatus = true; + bool rtstatus; struct bb_reg_def *pphyreg; for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { @@ -484,12 +484,12 @@ static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) switch (rfpath) { case RF90_PATH_A: - rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); + rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, + (enum radio_path) rfpath); break; case RF90_PATH_B: - rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); + rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, + (enum radio_path) rfpath); break; case RF90_PATH_C: break; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h index 39ff03685986..3aa520c1c171 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h @@ -34,11 +34,14 @@ #define RF6052_MAX_REG 0x3F #define RF6052_MAX_PATH 2 -extern void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -extern void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -extern void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -extern bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); +extern void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); +bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); + #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 390bbb5ee11d..b1cc4d44f534 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -42,58 +42,10 @@ #include "trx.h" #include "led.h" -static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - * */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - int rtl92c_init_sw_vars(struct ieee80211_hw *hw) { - int err; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - const struct firmware *firmware; - - rtl8192ce_bt_reg_init(hw); rtlpriv->dm.dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; @@ -101,12 +53,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->dm.thermalvalue = 0; rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - /* compatible 5G band 88ce just 2.4G band & smsp */ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | + rtlpci->receive_config = (RCR_APP_FCS | RCR_AMF | RCR_ADF | RCR_APP_MIC | @@ -129,49 +76,13 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0); - /* for LPS & IPS */ - rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; - rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 */ - rtl92c_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); + rtlpriv->rtlhal.pfirmware = (u8 *) vmalloc(0x4000); if (!rtlpriv->rtlhal.pfirmware) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Can't alloc buffer for fw.\n")); return 1; } - /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Failed to request firmware!\n")); - return 1; - } - if (firmware->size > 0x4000) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); - return 0; } @@ -192,19 +103,17 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .interrupt_recognized = rtl92ce_interrupt_recognized, .hw_init = rtl92ce_hw_init, .hw_disable = rtl92ce_card_disable, - .hw_suspend = rtl92ce_suspend, - .hw_resume = rtl92ce_resume, .enable_interrupt = rtl92ce_enable_interrupt, .disable_interrupt = rtl92ce_disable_interrupt, .set_network_type = rtl92ce_set_network_type, - .set_chk_bssid = rtl92ce_set_check_bssid, .set_qos = rtl92ce_set_qos, .set_bcn_reg = rtl92ce_set_beacon_related_registers, .set_bcn_intv = rtl92ce_set_beacon_interval, .update_interrupt_mask = rtl92ce_update_interrupt_mask, .get_hw_reg = rtl92ce_get_hw_reg, .set_hw_reg = rtl92ce_set_hw_reg, - .update_rate_tbl = rtl92ce_update_hal_rate_tbl, + .update_rate_table = rtl92ce_update_hal_rate_table, + .update_rate_mask = rtl92ce_update_hal_rate_mask, .fill_tx_desc = rtl92ce_tx_fill_desc, .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, .query_rx_desc = rtl92ce_rx_query_desc, @@ -214,7 +123,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .switch_channel = rtl92c_phy_sw_chnl, .dm_watchdog = rtl92c_dm_watchdog, .scan_operation_backup = rtl92c_phy_scan_operation_backup, - .set_rf_power_state = rtl92c_phy_set_rf_power_state, + .set_rf_power_state = rtl92ce_phy_set_rf_power_state, .led_control = rtl92ce_led_control, .set_desc = rtl92ce_set_desc, .get_desc = rtl92ce_get_desc, @@ -222,29 +131,27 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .enable_hw_sec = rtl92ce_enable_hw_security_config, .set_key = rtl92ce_set_key, .init_sw_leds = rtl92ce_init_sw_leds, + .deinit_sw_leds = rtl92ce_deinit_sw_leds, .get_bbreg = rtl92c_phy_query_bb_reg, .set_bbreg = rtl92c_phy_set_bb_reg, + .get_rfreg = rtl92ce_phy_query_rf_reg, .set_rfreg = rtl92ce_phy_set_rf_reg, - .get_rfreg = rtl92c_phy_query_rf_reg, + .cmd_send_packet = _rtl92c_cmd_send_packet, .phy_rf6052_config = rtl92ce_phy_rf6052_config, .phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower, .phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower, .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, + .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, }; static struct rtl_mod_params rtl92ce_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = false, - .fwctrl_lps = true, + .sw_crypto = 0, }; static struct rtl_hal_cfg rtl92ce_hal_cfg = { - .bar_id = 2, - .write_readback = true, .name = "rtl92c_pci", .fw_name = "rtlwifi/rtl8192cfw.bin", .ops = &rtl8192ce_hal_ops, @@ -268,8 +175,6 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, .maps[EFUSE_ANA8M] = EFUSE_ANA8M, .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, .maps[RWCAM] = REG_CAMCMD, .maps[WCAMI] = REG_CAMWRITE, @@ -334,7 +239,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; -DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { +static struct pci_device_id rtl92ce_pci_ids[] __devinitdata = { {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, @@ -352,13 +257,7 @@ MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); -module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); -module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); -module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); -MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); -MODULE_PARM_DESC(fwlps, "using linked fw control power save " - "(default 1 is open)\n"); static struct pci_driver rtl92ce_driver = { .name = KBUILD_MODNAME, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h index b7dc3263e433..36e657668c1e 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h @@ -33,9 +33,19 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw); void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); void rtl92c_init_var_map(struct ieee80211_hw *hw); +bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb); +void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); + u8 configtype); bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); + u8 configtype); +void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); +u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask); +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 54b2bd53d36a..aa2b5815600f 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -36,16 +36,42 @@ #include "trx.h" #include "led.h" -static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc, + unsigned int + skb_queue) { - __le16 fc = rtl_get_fc(skb); + enum rtl_desc_qsel qsel; - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc)) - return QSLT_MGNT; + if (unlikely(ieee80211_is_beacon(fc))) { + qsel = QSLT_BEACON; + return qsel; + } + + if (ieee80211_is_mgmt(fc)) { + qsel = QSLT_MGNT; + return qsel; + } - return skb->priority; + switch (skb_queue) { + case VO_QUEUE: + qsel = QSLT_VO; + break; + case VI_QUEUE: + qsel = QSLT_VI; + break; + case BE_QUEUE: + qsel = QSLT_BE; + break; + case BK_QUEUE: + qsel = QSLT_BK; + break; + default: + qsel = QSLT_BE; + RT_ASSERT(false, ("BE queue, skb_queue:%d," + " set qsel = 0x%X\n", skb_queue, QSLT_BE)); + break; + } + return qsel; } static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) @@ -229,7 +255,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, u8 evm, pwdb_all, rf_rx_num = 0; u8 i, max_spatial_stream; u32 rssi, total_rssi = 0; - bool in_powersavemode = false; bool is_cck_rate; is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); @@ -245,13 +270,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, u8 report, cck_highpwr; cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - if (!in_powersavemode) - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - else - cck_highpwr = false; - + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; report = cck_buf->cck_agc_rpt & 0xc0; @@ -377,7 +398,6 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) { - rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX; last_rssi = @@ -404,6 +424,10 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, if (!pstats->is_cck && pstats->packet_toself) { for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; rfpath++) { + + if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) + continue; + if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { rtlpriv->stats.rx_rssi_percentage[rfpath] = pstats->rx_mimo_signalstrength[rfpath]; @@ -699,7 +723,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *tcb_desc) + unsigned int queue_index) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -708,9 +732,16 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, bool defaultadapter = true; struct ieee80211_sta *sta; u8 *pdesc = (u8 *) pdesc_tx; + struct rtl_tcb_desc tcb_desc; + u8 *qc = ieee80211_get_qos_ctl(hdr); + u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; __le16 fc = hdr->frame_control; - u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); + u8 rate_flag = info->control.rates[0].flags; + + enum rtl_desc_qsel fw_qsel = + _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index); + bool firstseg = ((hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); @@ -720,68 +751,56 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - u8 bw_40 = 0; - - rcu_read_lock(); - sta = get_sta(hw, mac->vif, mac->bssid); - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); + rtl_get_tcb_desc(hw, info, skb, &tcb_desc); CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } if (firstseg) { SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); + SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate); - if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) + if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - if (info->flags & IEEE80211_TX_CTL_AMPDU) { + if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && + info->flags & IEEE80211_TX_CTL_AMPDU) { SET_TX_DESC_AGG_BREAK(pdesc, 1); SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); } SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && - !tcb_desc-> + SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable && + !tcb_desc. cts_enable) ? 1 : 0)); SET_TX_DESC_HW_RTS_ENABLE(pdesc, - ((tcb_desc->rts_enable - || tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); + ((tcb_desc.rts_enable + || tcb_desc.cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); + SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate); SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); + SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc); SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? - (tcb_desc->rts_use_shortpreamble ? 1 : 0) - : (tcb_desc->rts_use_shortgi ? 1 : 0))); + ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? + (tcb_desc.rts_use_shortpreamble ? 1 : 0) + : (tcb_desc.rts_use_shortgi ? 1 : 0))); - if (bw_40) { - if (tcb_desc->packet_bw) { + if (mac->bw_40) { + if (tcb_desc.packet_bw) { SET_TX_DESC_DATA_BW(pdesc, 1); SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); } else { SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); + + if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } } } else { SET_TX_DESC_DATA_BW(pdesc, 0); @@ -791,10 +810,13 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_LINIP(pdesc, 0); SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); } + rcu_read_unlock(); if (info->control.hw_key) { struct ieee80211_key_conf *keyconf = @@ -822,7 +844,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { @@ -833,24 +855,24 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, } } } - rcu_read_unlock(); SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); + SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id); } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); + SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index); } - if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { + if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && + ppsc->fwctrl_lps) { SET_TX_DESC_HWSEQ_EN(pdesc, 1); SET_TX_DESC_PKT_ID(pdesc, 8); @@ -901,7 +923,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); SET_TX_DESC_RATE_ID(pdesc, 7); SET_TX_DESC_MACID(pdesc, 0); @@ -999,7 +1021,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) return ret; } -void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); if (hw_queue == BEACON_QUEUE) { @@ -1010,3 +1032,35 @@ void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) } } +bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + u8 own; + unsigned long flags; + struct sk_buff *pskb = NULL; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + pdesc = &ring->desc[0]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); + + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); + + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + + return true; +} diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index 0f1177137501..803adcc80c96 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -532,9 +532,9 @@ #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ do { \ if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ else \ - memset(__pdesc, 0, _size); \ + memset((void *)__pdesc, 0, _size); \ } while (0); #define RX_HAL_IS_CCK_RATE(_pdesc)\ @@ -724,16 +724,17 @@ struct rx_desc_92c { void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc, struct ieee80211_tx_info *info, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); + struct sk_buff *skb, unsigned int qsel); bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, u8 *pdesc, struct sk_buff *skb); void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); -void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue); void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool b_firstseg, bool b_lastseg, struct sk_buff *skb); +bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); + #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 52e2af58c1ed..9444e76838cf 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -39,7 +39,6 @@ #include "mac.h" #include "dm.h" #include "hw.h" -#include "../rtl8192ce/hw.h" #include "trx.h" #include "led.h" #include "table.h" @@ -606,10 +605,10 @@ void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) if (!IS_NORMAL_CHIP(rtlhal->version)) return; tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? + rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n", - (tmp_u1b & BOOT_FROM_EEPROM) ? "EERROM" : "EFUSE")); + (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE")); rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n", (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!")); @@ -922,7 +921,7 @@ static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw, u8 out_ep_num, u8 queue_sel) { - u8 hq_sele = 0; + u8 hq_sele; struct rtl_priv *rtlpriv = rtl_priv(hw); switch (out_ep_num) { @@ -978,7 +977,7 @@ static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | + mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APP_FCS | RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); rtl_write_dword(rtlpriv, REG_RCR, mac->rx_conf); @@ -2183,9 +2182,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } } -void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) +void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h index 32f85cba106a..62af555bb61c 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h @@ -98,14 +98,13 @@ void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level); +void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw); void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +u8 _rtl92c_get_chnl_group(u8 chnl); int rtl92c_download_fw(struct ieee80211_hw *hw); void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 9a3d0239e27e..4e020e654e6b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -38,7 +38,7 @@ #include "table.h" u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) + enum radio_path rfpath, u32 regaddr, u32 bitmask) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 original_value, readback_value, bitshift; @@ -64,8 +64,8 @@ u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, } void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -163,7 +163,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) } bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { int i; u32 *phy_regarray_table; @@ -223,7 +223,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, } bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) + u8 configtype) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -459,7 +459,7 @@ void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) } } -static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, +bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -595,7 +595,7 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, } bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) + enum rf_pwrstate rfpwr_state) { struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool bresult = false; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h index ff81a61729d7..06299559ab68 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h @@ -34,17 +34,3 @@ bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); void rtl92c_phy_set_io(struct ieee80211_hw *hw); bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw); -u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask); -void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); -bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index c7576ec4744e..1c79c226f145 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -62,7 +62,7 @@ void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) } void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) + u8 *ppowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -389,7 +389,7 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, } void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) + u8 *ppowerlevel, u8 channel) { u32 writeVal[2], powerBase0[2], powerBase1[2]; u8 index = 0; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h index 500a2094b6bb..86c2728cfa00 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h @@ -43,9 +43,5 @@ extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, enum radio_path rfpath); -void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); #endif diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index bee7c1480f63..71244a38d49e 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -94,7 +94,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { .update_interrupt_mask = rtl92cu_update_interrupt_mask, .get_hw_reg = rtl92cu_get_hw_reg, .set_hw_reg = rtl92cu_set_hw_reg, - .update_rate_tbl = rtl92cu_update_hal_rate_table, + .update_rate_table = rtl92cu_update_hal_rate_table, .update_rate_mask = rtl92cu_update_hal_rate_mask, .fill_tx_desc = rtl92cu_tx_fill_desc, .fill_fake_txdesc = rtl92cu_fill_fake_txdesc, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 79c98f62175f..d0b0d43b9a6d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -498,14 +498,14 @@ static void _rtl_tx_desc_checksum(u8 *txdesc) void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - u8 queue_index, - struct rtl_tcb_desc *tcb_desc) + unsigned int queue_index) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta = info->control.sta = info->control.sta; + struct ieee80211_sta *sta; + struct rtl_tcb_desc tcb_desc; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; @@ -517,15 +517,15 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, u8 *txdesc; seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); + rtl_get_tcb_desc(hw, info, skb, &tcb_desc); txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); memset(txdesc, 0, RTL_TX_HEADER_SIZE); SET_TX_DESC_PKT_SIZE(txdesc, pktlen); SET_TX_DESC_LINIP(txdesc, 0); SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); - if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) + SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate); + if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) SET_TX_DESC_DATA_SHORTGI(txdesc, 1); if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -535,21 +535,21 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_AGG_BREAK(txdesc, 1); } SET_TX_DESC_SEQ(txdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && - !tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || - tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); + SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable && + !tcb_desc.cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable || + tcb_desc.cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); + SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate); SET_TX_DESC_RTS_BW(txdesc, 0); - SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); + SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc); SET_TX_DESC_RTS_SHORT(txdesc, - ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? - (tcb_desc->rts_use_shortpreamble ? 1 : 0) - : (tcb_desc->rts_use_shortgi ? 1 : 0))); + ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? + (tcb_desc.rts_use_shortpreamble ? 1 : 0) + : (tcb_desc.rts_use_shortgi ? 1 : 0))); if (mac->bw_40) { - if (tcb_desc->packet_bw) { + if (tcb_desc.packet_bw) { SET_TX_DESC_DATA_BW(txdesc, 1); SET_TX_DESC_DATA_SC(txdesc, 3); } else { @@ -590,7 +590,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); SET_TX_DESC_DISABLE_FB(txdesc, 0); - SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); + SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0); if (ieee80211_is_data_qos(fc)) { if (mac->rdg_en) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, @@ -600,11 +600,11 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, } } if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); + SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id); } else { - SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); + SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index); } if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && ppsc->fwctrl_lps) { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h index 53de5f66e242..b396d46edbb7 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h @@ -37,8 +37,6 @@ #define RTL92C_SIZE_MAX_RX_BUFFER 15360 /* 8192 */ #define RX_DRV_INFO_SIZE_UNIT 8 -#define RTL_AGG_ON 1 - enum usb_rx_agg_mode { USB_RX_AGG_DISABLE, USB_RX_AGG_DMA, @@ -421,8 +419,7 @@ struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *, void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, struct sk_buff *skb, - u8 queue_index, - struct rtl_tcb_desc *tcb_desc); + unsigned int queue_index); void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, u32 buffer_len, bool bIsPsPoll); void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.c b/trunk/drivers/net/wireless/rtlwifi/usb.c index a9367eba1ea7..f5d85735d642 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.c +++ b/trunk/drivers/net/wireless/rtlwifi/usb.c @@ -852,7 +852,6 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rtl_tx_desc *pdesc = NULL; - struct rtl_tcb_desc tcb_desc; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; u8 *pda_addr = hdr->addr1; @@ -861,17 +860,8 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, u8 tid = 0; u16 seq_number = 0; - if (ieee80211_is_auth(fc)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); - rtl_ips_nic_on(hw); - } - - if (rtlpriv->psc.sw_ps_enabled) { - if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && - !ieee80211_has_pm(fc)) - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - } - + if (ieee80211_is_mgmt(fc)) + rtl_tx_mgmt_proc(hw, skb); rtl_action_proc(hw, skb, true); if (is_multicast_ether_addr(pda_addr)) rtlpriv->stats.txbytesmulticast += skb->len; @@ -888,7 +878,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, seq_number <<= 4; } rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb, - hw_queue, &tcb_desc); + hw_queue); if (!ieee80211_has_morefrags(hdr->frame_control)) { if (qc) mac->tids[tid].seq_number = seq_number; @@ -897,8 +887,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); } -static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb, - struct rtl_tcb_desc *dummy) +static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.h b/trunk/drivers/net/wireless/rtlwifi/usb.h index d2a63fb3e1e6..abadfe918d30 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.h +++ b/trunk/drivers/net/wireless/rtlwifi/usb.h @@ -31,8 +31,6 @@ #include #include -#define RTL_RX_DESC_SIZE 24 - #define RTL_USB_DEVICE(vend, prod, cfg) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ diff --git a/trunk/drivers/net/wireless/rtlwifi/wifi.h b/trunk/drivers/net/wireless/rtlwifi/wifi.h index a406c616b697..01226f8e70f9 100644 --- a/trunk/drivers/net/wireless/rtlwifi/wifi.h +++ b/trunk/drivers/net/wireless/rtlwifi/wifi.h @@ -68,8 +68,6 @@ #define QBSS_LOAD_SIZE 5 #define MAX_WMMELE_LENGTH 64 -#define TOTAL_CAM_ENTRY 32 - /*slot time for 11g. */ #define RTL_SLOT_TIME_9 9 #define RTL_SLOT_TIME_20 20 @@ -96,10 +94,8 @@ #define CHANNEL_GROUP_MAX_5G 9 #define CHANNEL_MAX_NUMBER_2G 14 #define AVG_THERMAL_NUM 8 -#define MAX_TID_COUNT 9 /* for early mode */ -#define FCS_LEN 4 #define EM_HDR_LEN 8 enum intf_type { INTF_PCI = 0, @@ -163,8 +159,6 @@ enum hardware_type { (IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) #define IS_HARDWARE_TYPE_8723(rtlhal) \ (IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) -#define IS_HARDWARE_TYPE_8723U(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) enum scan_operation_backup_opt { SCAN_OPT_BACKUP = 0, @@ -303,9 +297,6 @@ enum hw_variables { HW_VAR_DATA_FILTER, }; -#define HWSET_MAX_SIZE 128 -#define EFUSE_MAX_SECTION 16 - enum _RT_MEDIA_STATUS { RT_MEDIA_DISCONNECT = 0, RT_MEDIA_CONNECT = 1 @@ -775,7 +766,7 @@ struct rtl_rfkill { #define IQK_MATRIX_REG_NUM 8 #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) struct iqk_matrix_regs { - bool iqk_done; + bool b_iqk_done; long value[1][IQK_MATRIX_REG_NUM]; }; @@ -852,7 +843,6 @@ struct rtl_phy { bool apk_done; u32 reg_rf3c[2]; /* pathA / pathB */ - /* bfsync */ u8 framesync; u32 framesync_c34; @@ -862,10 +852,6 @@ struct rtl_phy { }; #define MAX_TID_COUNT 9 -#define RTL_AGG_STOP 0 -#define RTL_AGG_PROGRESS 1 -#define RTL_AGG_START 2 -#define RTL_AGG_OPERATIONAL 3 #define RTL_AGG_OFF 0 #define RTL_AGG_ON 1 #define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 @@ -885,13 +871,6 @@ struct rtl_tid_data { struct rtl_ht_agg agg; }; -struct rtl_sta_info { - u8 ratr_index; - u8 wireless_mode; - u8 mimo_ps; - struct rtl_tid_data tids[MAX_TID_COUNT]; -} __packed; - struct rtl_priv; struct rtl_io { struct device *dev; @@ -915,7 +894,6 @@ struct rtl_io { u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len, u8 *pdata); - }; struct rtl_mac { @@ -938,8 +916,6 @@ struct rtl_mac { int n_channels; int n_bitrates; - bool offchan_deley; - /*filters */ u32 rx_conf; u16 rx_mgt_filter; @@ -1056,9 +1032,7 @@ struct rtl_security { enum rt_enc_alg pairwise_enc_algorithm; /*Encryption Algorithm for Brocast/Multicast */ enum rt_enc_alg group_enc_algorithm; - /*Cam Entry Bitmap */ - u32 hwsec_cam_bitmap; - u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; + /*local Key buffer, indx 0 is for pairwise key 1-4 is for agoup key. */ u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; @@ -1079,7 +1053,7 @@ struct rtl_dm { bool current_turbo_edca; bool is_any_nonbepkts; /*out dm */ bool is_cur_rdlstate; - bool txpower_trackinginit; + bool txpower_trackingInit; bool disable_framebursting; bool cck_inch14; bool txpower_tracking; @@ -1105,6 +1079,7 @@ struct rtl_dm { bool disable_tx_int; char ofdm_index[2]; char cck_index; + u8 power_index_backup[6]; }; #define EFUSE_MAX_LOGICAL_SIZE 256 @@ -1200,7 +1175,6 @@ struct rtl_ps_ctl { * otherwise Offset[560h] = 0x00. * */ bool support_aspm; - bool support_backdoor; /*for LPS */ @@ -1227,6 +1201,7 @@ struct rtl_ps_ctl { /*just for PCIE ASPM */ u8 const_amdpci_aspm; + bool pwrdown_mode; enum rf_pwrstate inactive_pwrstate; @@ -1307,10 +1282,6 @@ struct rt_link_detect { bool busytraffic; bool higher_busytraffic; bool higher_busyrxtraffic; - - u32 tidtx_in4period[MAX_TID_COUNT][4]; - u32 tidtx_inperiod[MAX_TID_COUNT]; - bool higher_busytxtraffic[MAX_TID_COUNT]; }; struct rtl_tcb_desc { @@ -1373,15 +1344,13 @@ struct rtl_hal_ops { u32 add_msr, u32 rm_msr); void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*update_rate_tbl) (struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); + void (*update_rate_table) (struct ieee80211_hw *hw); void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); void (*fill_tx_desc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); - void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, + struct sk_buff *skb, unsigned int queue_index); + void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 * pDesc, u32 buffer_len, bool bIsPsPoll); void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, @@ -1401,10 +1370,10 @@ struct rtl_hal_ops { enum led_ctl_mode ledaction); void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val); u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name); - void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); + void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue); void (*enable_hw_sec) (struct ieee80211_hw *hw); void (*set_key) (struct ieee80211_hw *hw, u32 key_index, - u8 *macaddr, bool is_group, u8 enc_algo, + u8 *p_macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); void (*init_sw_leds) (struct ieee80211_hw *hw); void (*deinit_sw_leds) (struct ieee80211_hw *hw); @@ -1415,7 +1384,6 @@ struct rtl_hal_ops { u32 regaddr, u32 bitmask); void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask, u32 data); - void (*linked_set_reg) (struct ieee80211_hw *hw); bool (*phy_rf6052_config) (struct ieee80211_hw *hw); void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, u8 *powerlevel); @@ -1436,9 +1404,7 @@ struct rtl_intf_ops { int (*adapter_start) (struct ieee80211_hw *hw); void (*adapter_stop) (struct ieee80211_hw *hw); - int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc); - void (*flush)(struct ieee80211_hw *hw, bool drop); + int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb); int (*reset_trx_ring) (struct ieee80211_hw *hw); bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1452,15 +1418,6 @@ struct rtl_intf_ops { struct rtl_mod_params { /* default: 0 = using hardware encryption */ int sw_crypto; - - /* default: 1 = using no linked power save */ - bool inactiveps; - - /* default: 1 = using linked sw power save */ - bool swctrl_lps; - - /* default: 1 = using linked fw power save */ - bool fwctrl_lps; }; struct rtl_hal_usbint_cfg { @@ -1488,7 +1445,6 @@ struct rtl_hal_usbint_cfg { struct rtl_hal_cfg { u8 bar_id; - bool write_readback; char *name; char *fw_name; struct rtl_hal_ops *ops; @@ -1513,6 +1469,7 @@ struct rtl_locks { spinlock_t rf_lock; spinlock_t lps_lock; spinlock_t waitq_lock; + spinlock_t tx_urb_lock; /*Dual mac*/ spinlock_t cck_and_rw_pagea_lock; @@ -1664,19 +1621,19 @@ struct bt_coexist_info { u32 bt_edca_ul; u32 bt_edca_dl; - bool init_set; - bool bt_busy_traffic; - bool bt_traffic_mode_set; - bool bt_non_traffic_mode_set; + bool b_init_set; + bool b_bt_busy_traffic; + bool b_bt_traffic_mode_set; + bool b_bt_non_traffic_mode_set; - bool fw_coexist_all_off; - bool sw_coexist_all_off; + bool b_fw_coexist_all_off; + bool b_sw_coexist_all_off; u32 current_state; u32 previous_state; u8 bt_pre_rssi_state; - u8 reg_bt_iso; - u8 reg_bt_sco; + u8 b_reg_bt_iso; + u8 b_reg_bt_sco; }; @@ -1696,23 +1653,13 @@ struct bt_coexist_info { #define EF4BYTE(_val) \ (le32_to_cpu(_val)) -/* Read data from memory */ -#define READEF1BYTE(_ptr) \ - EF1BYTE(*((u8 *)(_ptr))) /* Read le16 data from memory and convert to host ordering */ #define READEF2BYTE(_ptr) \ EF2BYTE(*((u16 *)(_ptr))) -#define READEF4BYTE(_ptr) \ - EF4BYTE(*((u32 *)(_ptr))) -/* Write data to memory */ -#define WRITEEF1BYTE(_ptr, _val) \ - (*((u8 *)(_ptr))) = EF1BYTE(_val) /* Write le16 data to memory in host ordering */ #define WRITEEF2BYTE(_ptr, _val) \ (*((u16 *)(_ptr))) = EF2BYTE(_val) -#define WRITEEF4BYTE(_ptr, _val) \ - (*((u16 *)(_ptr))) = EF2BYTE(_val) /* Create a bit mask * Examples: @@ -1751,25 +1698,6 @@ struct bt_coexist_info { #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ (EF1BYTE(*((u8 *)(__pstart)))) -/*Description: -Translate subfield (continuous bits in little-endian) of 4-byte -value to host byte ordering.*/ -#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ - BIT_LEN_MASK_32(__bitlen) \ - ) -#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ - BIT_LEN_MASK_16(__bitlen) \ - ) -#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ - BIT_LEN_MASK_8(__bitlen) \ - ) - /* Description: * Mask subfield (continuous bits in little-endian) of 4-byte value * and return the result in 4-byte value in host byte ordering. @@ -1793,18 +1721,6 @@ value to host byte ordering.*/ /* Description: * Set subfield of little-endian 4-byte value to specified value. */ -#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u32 *)(__pstart)) = EF4BYTE \ - ( \ - LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \ - ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \ - ); -#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u16 *)(__pstart)) = EF2BYTE \ - ( \ - LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ - ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ - ); #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ *((u8 *)(__pstart)) = EF1BYTE \ ( \ @@ -1812,16 +1728,12 @@ value to host byte ordering.*/ ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ ); -#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ - (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) - /**************************************** mem access macro define end ****************************************/ #define byte(x, n) ((x >> (8 * n)) & 0xff) -#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) #define RTL_WATCH_DOG_TIME 2000 #define MSECS(t) msecs_to_jiffies(t) #define WLAN_FC_GET_VERS(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_VERS) @@ -1856,15 +1768,6 @@ value to host byte ordering.*/ #define container_of_dwork_rtl(x, y, z) \ container_of(container_of(x, struct delayed_work, work), y, z) -#define FILL_OCTET_STRING(_os, _octet, _len) \ - (_os).octet = (u8 *)(_octet); \ - (_os).length = (_len); - -#define CP_MACADDR(des, src) \ - ((des)[0] = (src)[0], (des)[1] = (src)[1],\ - (des)[2] = (src)[2], (des)[3] = (src)[3],\ - (des)[4] = (src)[4], (des)[5] = (src)[5]) - static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) { return rtlpriv->io.read8_sync(rtlpriv, addr); @@ -1883,26 +1786,17 @@ static inline u32 rtl_read_dword(struct rtl_priv *rtlpriv, u32 addr) static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) { rtlpriv->io.write8_async(rtlpriv, addr, val8); - - if (rtlpriv->cfg->write_readback) - rtlpriv->io.read8_sync(rtlpriv, addr); } static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) { rtlpriv->io.write16_async(rtlpriv, addr, val16); - - if (rtlpriv->cfg->write_readback) - rtlpriv->io.read16_sync(rtlpriv, addr); } static inline void rtl_write_dword(struct rtl_priv *rtlpriv, u32 addr, u32 val32) { rtlpriv->io.write32_async(rtlpriv, addr, val32); - - if (rtlpriv->cfg->write_readback) - rtlpriv->io.read32_sync(rtlpriv, addr); } static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, @@ -1961,31 +1855,4 @@ static inline u8 get_rf_type(struct rtl_phy *rtlphy) return rtlphy->rf_type; } -static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) -{ - return (struct ieee80211_hdr *)(skb->data); -} - -static inline __le16 rtl_get_fc(struct sk_buff *skb) -{ - return rtl_get_hdr(skb)->frame_control; -} - -static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) -{ - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -} - -static inline u16 rtl_get_tid(struct sk_buff *skb) -{ - return rtl_get_tid_h(rtl_get_hdr(skb)); -} - -static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u8 *bssid) -{ - return ieee80211_find_sta(vif, bssid); -} - #endif diff --git a/trunk/drivers/net/wireless/wl1251/cmd.h b/trunk/drivers/net/wireless/wl1251/cmd.h index 79ca5273c9e9..e5c74c631374 100644 --- a/trunk/drivers/net/wireless/wl1251/cmd.h +++ b/trunk/drivers/net/wireless/wl1251/cmd.h @@ -313,8 +313,8 @@ struct wl1251_cmd_vbm_update { } __packed; enum wl1251_cmd_ps_mode { - CHIP_ACTIVE_MODE, - CHIP_POWER_SAVE_MODE + STATION_ACTIVE_MODE, + STATION_POWER_SAVE_MODE }; struct wl1251_cmd_ps_params { diff --git a/trunk/drivers/net/wireless/wl1251/event.c b/trunk/drivers/net/wireless/wl1251/event.c index 9f15ccaf8f05..dfc4579acb06 100644 --- a/trunk/drivers/net/wireless/wl1251/event.c +++ b/trunk/drivers/net/wireless/wl1251/event.c @@ -68,16 +68,14 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) if (vector & BSS_LOSE_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); - if (wl->psm_requested && - wl->station_mode != STATION_ACTIVE_MODE) { + if (wl->psm_requested && wl->psm) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; } } - if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && - wl->station_mode != STATION_ACTIVE_MODE) { + if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) { wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); /* indicate to the stack, that beacons have been lost */ diff --git a/trunk/drivers/net/wireless/wl1251/main.c b/trunk/drivers/net/wireless/wl1251/main.c index a14a48c99cdc..12c9e635a6d6 100644 --- a/trunk/drivers/net/wireless/wl1251/main.c +++ b/trunk/drivers/net/wireless/wl1251/main.c @@ -497,7 +497,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) wl->rx_last_id = 0; wl->next_tx_complete = 0; wl->elp = false; - wl->station_mode = STATION_ACTIVE_MODE; + wl->psm = 0; wl->tx_queue_stopped = false; wl->power_level = WL1251_DEFAULT_POWER_LEVEL; wl->rssi_thold = 0; @@ -632,29 +632,13 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) wl->psm_requested = false; - if (wl->station_mode != STATION_ACTIVE_MODE) { + if (wl->psm) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) goto out_sleep; } } - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (conf->flags & IEEE80211_CONF_IDLE) { - ret = wl1251_ps_set_mode(wl, STATION_IDLE); - if (ret < 0) - goto out_sleep; - } else { - ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - goto out_sleep; - ret = wl1251_join(wl, wl->bss_type, wl->channel, - wl->beacon_int, wl->dtim_period); - if (ret < 0) - goto out_sleep; - } - } - if (conf->power_level != wl->power_level) { ret = wl1251_acx_tx_power(wl, conf->power_level); if (ret < 0) @@ -1400,7 +1384,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) wl->rx_config = WL1251_DEFAULT_RX_CONFIG; wl->rx_filter = WL1251_DEFAULT_RX_FILTER; wl->elp = false; - wl->station_mode = STATION_ACTIVE_MODE; + wl->psm = 0; wl->psm_requested = false; wl->tx_queue_stopped = false; wl->power_level = WL1251_DEFAULT_POWER_LEVEL; diff --git a/trunk/drivers/net/wireless/wl1251/ps.c b/trunk/drivers/net/wireless/wl1251/ps.c index db719f7d2692..9cc514703d2a 100644 --- a/trunk/drivers/net/wireless/wl1251/ps.c +++ b/trunk/drivers/net/wireless/wl1251/ps.c @@ -39,7 +39,7 @@ void wl1251_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->elp || wl->station_mode == STATION_ACTIVE_MODE) + if (wl->elp || !wl->psm) goto out; wl1251_debug(DEBUG_PSM, "chip to elp"); @@ -57,7 +57,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl) { unsigned long delay; - if (wl->station_mode != STATION_ACTIVE_MODE) { + if (wl->psm) { delay = msecs_to_jiffies(ELP_ENTRY_DELAY); ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); } @@ -104,7 +104,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) return 0; } -int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode) +int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) { int ret; @@ -128,24 +128,15 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode) if (ret < 0) return ret; - ret = wl1251_cmd_ps_mode(wl, CHIP_POWER_SAVE_MODE); + ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); if (ret < 0) return ret; - break; - case STATION_IDLE: - wl1251_debug(DEBUG_PSM, "entering idle"); - ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); - if (ret < 0) - return ret; - - ret = wl1251_cmd_template_set(wl, CMD_DISCONNECT, NULL, 0); - if (ret < 0) - return ret; + wl->psm = 1; break; case STATION_ACTIVE_MODE: default: @@ -172,13 +163,13 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode) if (ret < 0) return ret; - ret = wl1251_cmd_ps_mode(wl, CHIP_ACTIVE_MODE); + ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; + wl->psm = 0; break; } - wl->station_mode = mode; return ret; } diff --git a/trunk/drivers/net/wireless/wl1251/ps.h b/trunk/drivers/net/wireless/wl1251/ps.h index 75efad246d67..55c3dda75e69 100644 --- a/trunk/drivers/net/wireless/wl1251/ps.h +++ b/trunk/drivers/net/wireless/wl1251/ps.h @@ -26,7 +26,7 @@ #include "wl1251.h" #include "acx.h" -int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode); +int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); void wl1251_ps_elp_sleep(struct wl1251 *wl); int wl1251_ps_elp_wakeup(struct wl1251 *wl); void wl1251_elp_work(struct work_struct *work); diff --git a/trunk/drivers/net/wireless/wl1251/wl1251.h b/trunk/drivers/net/wireless/wl1251/wl1251.h index a77f1bbbed0a..bb23cd522b22 100644 --- a/trunk/drivers/net/wireless/wl1251/wl1251.h +++ b/trunk/drivers/net/wireless/wl1251/wl1251.h @@ -129,12 +129,6 @@ enum wl1251_partition_type { PART_TABLE_LEN }; -enum wl1251_station_mode { - STATION_ACTIVE_MODE, - STATION_POWER_SAVE_MODE, - STATION_IDLE, -}; - struct wl1251_partition { u32 size; u32 start; @@ -364,7 +358,8 @@ struct wl1251 { struct delayed_work elp_work; - enum wl1251_station_mode station_mode; + /* we can be in psm, but not in elp, we have to differentiate */ + bool psm; /* PSM mode requested */ bool psm_requested; diff --git a/trunk/drivers/net/wireless/wl12xx/Kconfig b/trunk/drivers/net/wireless/wl12xx/Kconfig index 35ce7b0f4a60..692ebff38fc8 100644 --- a/trunk/drivers/net/wireless/wl12xx/Kconfig +++ b/trunk/drivers/net/wireless/wl12xx/Kconfig @@ -3,7 +3,7 @@ menuconfig WL12XX_MENU depends on MAC80211 && EXPERIMENTAL ---help--- This will enable TI wl12xx driver support for the following chips: - wl1271, wl1273, wl1281 and wl1283. + wl1271 and wl1273. The drivers make use of the mac80211 stack. config WL12XX diff --git a/trunk/drivers/net/wireless/wl12xx/acx.c b/trunk/drivers/net/wireless/wl12xx/acx.c index a5c9c0aff83f..a3db755ceeda 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.c +++ b/trunk/drivers/net/wireless/wl12xx/acx.c @@ -965,13 +965,10 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) } /* memory config */ - /* FIXME: for now we always use mem_wl127x for AP, because it - * doesn't support dynamic memory and we don't have the - * optimal values for wl128x without dynamic memory yet */ - mem_conf->num_stations = wl->conf.mem_wl127x.num_stations; - mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num; - mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num; - mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles; + mem_conf->num_stations = wl->conf.mem.num_stations; + mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; + mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; + mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, @@ -989,7 +986,6 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) { struct wl1271_acx_sta_config_memory *mem_conf; - struct conf_memory_settings *mem; int ret; wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); @@ -1000,21 +996,16 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) goto out; } - if (wl->chip.id == CHIP_ID_1283_PG20) - mem = &wl->conf.mem_wl128x; - else - mem = &wl->conf.mem_wl127x; - /* memory config */ - mem_conf->num_stations = mem->num_stations; - mem_conf->rx_mem_block_num = mem->rx_block_num; - mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; - mem_conf->num_ssid_profiles = mem->ssid_profiles; + mem_conf->num_stations = wl->conf.mem.num_stations; + mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; + mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; + mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); - mem_conf->dyn_mem_enable = mem->dynamic_memory; - mem_conf->tx_free_req = mem->min_req_tx_blocks; - mem_conf->rx_free_req = mem->min_req_rx_blocks; - mem_conf->tx_min = mem->tx_min; + mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory; + mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks; + mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks; + mem_conf->tx_min = wl->conf.mem.tx_min; ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, sizeof(*mem_conf)); @@ -1028,32 +1019,6 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) return ret; } -int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) -{ - struct wl1271_acx_host_config_bitmap *bitmap_conf; - int ret; - - bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); - if (!bitmap_conf) { - ret = -ENOMEM; - goto out; - } - - bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); - - ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, - bitmap_conf, sizeof(*bitmap_conf)); - if (ret < 0) { - wl1271_warning("wl1271 bitmap config opt failed: %d", ret); - goto out; - } - -out: - kfree(bitmap_conf); - - return ret; -} - int wl1271_acx_init_mem_config(struct wl1271 *wl) { int ret; @@ -1524,46 +1489,22 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) return ret; } -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) +int wl1271_acx_max_tx_retry(struct wl1271 *wl) { - struct wl1271_acx_ap_max_tx_retry *acx = NULL; + struct wl1271_acx_max_tx_retry *acx = NULL; int ret; - wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); + wl1271_debug(DEBUG_ACX, "acx max tx retry"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) return -ENOMEM; - acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); + acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); if (ret < 0) { - wl1271_warning("acx ap max tx retry failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl) -{ - struct wl1271_acx_sta_max_tx_retry *acx = NULL; - int ret; - - wl1271_debug(DEBUG_ACX, "acx sta max tx retry"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) - return -ENOMEM; - - acx->max_tx_retry = wl->conf.tx.max_tx_retries; - - ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("acx sta max tx retry failed: %d", ret); + wl1271_warning("acx max tx retry failed: %d", ret); goto out; } diff --git a/trunk/drivers/net/wireless/wl12xx/acx.h b/trunk/drivers/net/wireless/wl12xx/acx.h index 942908cd53a3..dd19b01d807b 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.h +++ b/trunk/drivers/net/wireless/wl12xx/acx.h @@ -939,16 +939,6 @@ struct wl1271_acx_keep_alive_config { u8 padding; } __packed; -#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) -#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) -#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) - -struct wl1271_acx_host_config_bitmap { - struct acx_header header; - - __le32 host_cfg_bitmap; -} __packed; - enum { WL1271_ACX_TRIG_TYPE_LEVEL = 0, WL1271_ACX_TRIG_TYPE_EDGE, @@ -1145,7 +1135,7 @@ struct wl1271_acx_fw_tsf_information { u8 padding[3]; } __packed; -struct wl1271_acx_ap_max_tx_retry { +struct wl1271_acx_max_tx_retry { struct acx_header header; /* @@ -1156,13 +1146,6 @@ struct wl1271_acx_ap_max_tx_retry { u8 padding_1[2]; } __packed; -struct wl1271_acx_sta_max_tx_retry { - struct acx_header header; - - u8 max_tx_retry; - u8 padding_1[3]; -} __packed; - struct wl1271_acx_config_ps { struct acx_header header; @@ -1292,7 +1275,6 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); -int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); @@ -1314,8 +1296,7 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl, int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); -int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); diff --git a/trunk/drivers/net/wireless/wl12xx/boot.c b/trunk/drivers/net/wireless/wl12xx/boot.c index d263ebb6f974..6934dffd5174 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.c +++ b/trunk/drivers/net/wireless/wl12xx/boot.c @@ -22,7 +22,6 @@ */ #include -#include #include "acx.h" #include "reg.h" @@ -244,58 +243,34 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) if (wl->nvs == NULL) return -ENODEV; - if (wl->chip.id == CHIP_ID_1283_PG20) { - struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; - - if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) { - if (nvs->general_params.dual_mode_select) - wl->enable_11a = true; - } else { - wl1271_error("nvs size is not as expected: %zu != %zu", - wl->nvs_len, - sizeof(struct wl128x_nvs_file)); - kfree(wl->nvs); - wl->nvs = NULL; - wl->nvs_len = 0; - return -EILSEQ; - } - - /* only the first part of the NVS needs to be uploaded */ - nvs_len = sizeof(nvs->nvs); - nvs_ptr = (u8 *)nvs->nvs; - - } else { - struct wl1271_nvs_file *nvs = - (struct wl1271_nvs_file *)wl->nvs; - /* - * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz - * band configurations) can be removed when those NVS files stop - * floating around. - */ - if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || - wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { - /* for now 11a is unsupported in AP mode */ - if (wl->bss_type != BSS_TYPE_AP_BSS && - nvs->general_params.dual_mode_select) - wl->enable_11a = true; - } - - if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && - (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || - wl->enable_11a)) { - wl1271_error("nvs size is not as expected: %zu != %zu", - wl->nvs_len, sizeof(struct wl1271_nvs_file)); - kfree(wl->nvs); - wl->nvs = NULL; - wl->nvs_len = 0; - return -EILSEQ; - } + /* + * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band + * configurations) can be removed when those NVS files stop floating + * around. + */ + if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || + wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { + /* for now 11a is unsupported in AP mode */ + if (wl->bss_type != BSS_TYPE_AP_BSS && + wl->nvs->general_params.dual_mode_select) + wl->enable_11a = true; + } - /* only the first part of the NVS needs to be uploaded */ - nvs_len = sizeof(nvs->nvs); - nvs_ptr = (u8 *) nvs->nvs; + if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && + (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || + wl->enable_11a)) { + wl1271_error("nvs size is not as expected: %zu != %zu", + wl->nvs_len, sizeof(struct wl1271_nvs_file)); + kfree(wl->nvs); + wl->nvs = NULL; + wl->nvs_len = 0; + return -EILSEQ; } + /* only the first part of the NVS needs to be uploaded */ + nvs_len = sizeof(wl->nvs->nvs); + nvs_ptr = (u8 *)wl->nvs->nvs; + /* update current MAC address to NVS */ nvs_ptr[11] = wl->mac_addr[0]; nvs_ptr[10] = wl->mac_addr[1]; @@ -344,13 +319,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) /* * We've reached the first zero length, the first NVS table * is located at an aligned offset which is at least 7 bytes further. - * NOTE: The wl->nvs->nvs element must be first, in order to - * simplify the casting, we assume it is at the beginning of - * the wl->nvs structure. */ - nvs_ptr = (u8 *)wl->nvs + - ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); - nvs_len -= nvs_ptr - (u8 *)wl->nvs; + nvs_ptr = (u8 *)wl->nvs->nvs + + ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); + nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; /* Now we must set the partition correctly */ wl1271_set_partition(wl, &part_table[PART_WORK]); @@ -478,14 +450,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | - SOFT_GEMINI_SENSE_EVENT_ID | - MAX_TX_RETRY_EVENT_ID; + SOFT_GEMINI_SENSE_EVENT_ID; if (wl->bss_type == BSS_TYPE_AP_BSS) - wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | - INACTIVE_STA_EVENT_ID; - else - wl->event_mask |= DUMMY_PACKET_EVENT_ID; + wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { @@ -525,159 +493,24 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; } -static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) -{ - u16 spare_reg; - - /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ - spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); - if (spare_reg == 0xFFFF) - return -EFAULT; - spare_reg |= (BIT(3) | BIT(5) | BIT(6)); - wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); - - /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ - wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, - WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); - - /* Delay execution for 15msec, to let the HW settle */ - mdelay(15); - - return 0; -} - -static bool wl128x_is_tcxo_valid(struct wl1271 *wl) -{ - u16 tcxo_detection; - - tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG); - if (tcxo_detection & TCXO_DET_FAILED) - return false; - - return true; -} - -static bool wl128x_is_fref_valid(struct wl1271 *wl) -{ - u16 fref_detection; - - fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG); - if (fref_detection & FREF_CLK_DETECT_FAIL) - return false; - - return true; -} - -static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) -{ - wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); - wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); - wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); - - return 0; -} - -static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) -{ - u16 spare_reg; - u16 pll_config; - u8 input_freq; - - /* Mask bits [3:1] in the sys_clk_cfg register */ - spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); - if (spare_reg == 0xFFFF) - return -EFAULT; - spare_reg |= BIT(2); - wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); - - /* Handle special cases of the TCXO clock */ - if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || - wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) - return wl128x_manually_configure_mcs_pll(wl); - - /* Set the input frequency according to the selected clock source */ - input_freq = (clk & 1) + 1; - - pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG); - if (pll_config == 0xFFFF) - return -EFAULT; - pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); - pll_config |= MCS_PLL_ENABLE_HP; - wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); - - return 0; -} - -/* - * WL128x has two clocks input - TCXO and FREF. - * TCXO is the main clock of the device, while FREF is used to sync - * between the GPS and the cellular modem. - * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used - * as the WLAN/BT main clock. - */ -static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) -{ - u16 sys_clk_cfg; - - /* For XTAL-only modes, FREF will be used after switching from TCXO */ - if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || - wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { - if (!wl128x_switch_tcxo_to_fref(wl)) - return -EINVAL; - goto fref_clk; - } - - /* Query the HW, to determine which clock source we should use */ - sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); - if (sys_clk_cfg == 0xFFFF) - return -EINVAL; - if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) - goto fref_clk; - - /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ - if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || - wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { - if (!wl128x_switch_tcxo_to_fref(wl)) - return -EINVAL; - goto fref_clk; - } - - /* TCXO clock is selected */ - if (!wl128x_is_tcxo_valid(wl)) - return -EINVAL; - *selected_clock = wl->tcxo_clock; - goto config_mcs_pll; - -fref_clk: - /* FREF clock is selected */ - if (!wl128x_is_fref_valid(wl)) - return -EINVAL; - *selected_clock = wl->ref_clock; - -config_mcs_pll: - return wl128x_configure_mcs_pll(wl, *selected_clock); -} - -static int wl127x_boot_clk(struct wl1271 *wl) +/* uploads NVS and firmware */ +int wl1271_load_firmware(struct wl1271 *wl) { - u32 pause; - u32 clk; + int ret = 0; + u32 tmp, clk, pause; wl1271_boot_hw_version(wl); - if (wl->ref_clock == CONF_REF_CLK_19_2_E || - wl->ref_clock == CONF_REF_CLK_38_4_E || - wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) + if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; - else if (wl->ref_clock == CONF_REF_CLK_26_E || - wl->ref_clock == CONF_REF_CLK_52_E) + else if (wl->ref_clock == 1 || wl->ref_clock == 3) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; - if (wl->ref_clock != CONF_REF_CLK_19_2_E) { + if (wl->ref_clock != 0) { u16 val; /* Set clock type (open drain) */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); @@ -707,26 +540,6 @@ static int wl127x_boot_clk(struct wl1271 *wl) pause |= WU_COUNTER_PAUSE_VAL; wl1271_write32(wl, WU_COUNTER_PAUSE, pause); - return 0; -} - -/* uploads NVS and firmware */ -int wl1271_load_firmware(struct wl1271 *wl) -{ - int ret = 0; - u32 tmp, clk; - int selected_clock = -1; - - if (wl->chip.id == CHIP_ID_1283_PG20) { - ret = wl128x_boot_clk(wl, &selected_clock); - if (ret < 0) - goto out; - } else { - ret = wl127x_boot_clk(wl); - if (ret < 0) - goto out; - } - /* Continue the ELP wake up sequence */ wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); @@ -742,12 +555,7 @@ int wl1271_load_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - if (wl->chip.id == CHIP_ID_1283_PG20) { - clk |= ((selected_clock & 0x3) << 1) << 4; - } else { - clk |= (wl->ref_clock << 1) << 4; - } - + clk |= (wl->ref_clock << 1) << 4; wl1271_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); @@ -777,12 +585,16 @@ int wl1271_load_firmware(struct wl1271 *wl) /* 6. read the EEPROM parameters */ tmp = wl1271_read32(wl, SCR_PAD2); + ret = wl1271_boot_write_irq_polarity(wl); + if (ret < 0) + goto out; + + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, + WL1271_ACX_ALL_EVENTS_VECTOR); + /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ - if (wl->chip.id == CHIP_ID_1283_PG20) - wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds); - ret = wl1271_boot_upload_firmware(wl); if (ret < 0) goto out; @@ -806,13 +618,6 @@ int wl1271_boot(struct wl1271 *wl) if (ret < 0) goto out; - ret = wl1271_boot_write_irq_polarity(wl); - if (ret < 0) - goto out; - - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_ALL_EVENTS_VECTOR); - /* Enable firmware interrupts now */ wl1271_boot_enable_interrupts(wl); diff --git a/trunk/drivers/net/wireless/wl12xx/boot.h b/trunk/drivers/net/wireless/wl12xx/boot.h index e8f8255bbabe..17229b86fc71 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.h +++ b/trunk/drivers/net/wireless/wl12xx/boot.h @@ -74,56 +74,4 @@ struct wl1271_static_data { #define FREF_CLK_POLARITY_BITS 0xfffff8ff #define CLK_REQ_OUTN_SEL 0x700 -/* PLL configuration algorithm for wl128x */ -#define SYS_CLK_CFG_REG 0x2200 -/* Bit[0] - 0-TCXO, 1-FREF */ -#define MCS_PLL_CLK_SEL_FREF BIT(0) -/* Bit[3:2] - 01-TCXO, 10-FREF */ -#define WL_CLK_REQ_TYPE_FREF BIT(3) -#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) -/* Bit[4] - 0-TCXO, 1-FREF */ -#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) - -#define TCXO_ILOAD_INT_REG 0x2264 -#define TCXO_CLK_DETECT_REG 0x2266 - -#define TCXO_DET_FAILED BIT(4) - -#define FREF_ILOAD_INT_REG 0x2084 -#define FREF_CLK_DETECT_REG 0x2086 -#define FREF_CLK_DETECT_FAIL BIT(4) - -/* Use this reg for masking during driver access */ -#define WL_SPARE_REG 0x2320 -#define WL_SPARE_VAL BIT(2) -/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ -#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) - -#define PLL_LOCK_COUNTERS_REG 0xD8C -#define PLL_LOCK_COUNTERS_COEX 0x0F -#define PLL_LOCK_COUNTERS_MCS 0xF0 -#define MCS_PLL_OVERRIDE_REG 0xD90 -#define MCS_PLL_CONFIG_REG 0xD92 -#define MCS_SEL_IN_FREQ_MASK 0x0070 -#define MCS_SEL_IN_FREQ_SHIFT 4 -#define MCS_PLL_CONFIG_REG_VAL 0x73 -#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) - -#define MCS_PLL_M_REG 0xD94 -#define MCS_PLL_N_REG 0xD96 -#define MCS_PLL_M_REG_VAL 0xC8 -#define MCS_PLL_N_REG_VAL 0x07 - -#define SDIO_IO_DS 0xd14 - -/* SDIO/wSPI DS configuration values */ -enum { - HCI_IO_DS_8MA = 0, - HCI_IO_DS_4MA = 1, /* default */ - HCI_IO_DS_6MA = 2, - HCI_IO_DS_2MA = 3, -}; - -/* end PLL configuration algorithm for wl128x */ - #endif diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.c b/trunk/drivers/net/wireless/wl12xx/cmd.c index d48331682e7e..f0aa7ab97bf7 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.c +++ b/trunk/drivers/net/wireless/wl12xx/cmd.c @@ -110,47 +110,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, int wl1271_cmd_general_parms(struct wl1271 *wl) { struct wl1271_general_parms_cmd *gen_parms; - struct wl1271_ini_general_params *gp = - &((struct wl1271_nvs_file *)wl->nvs)->general_params; - bool answer = false; - int ret; - - if (!wl->nvs) - return -ENODEV; - - gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); - if (!gen_parms) - return -ENOMEM; - - gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; - - memcpy(&gen_parms->general_params, gp, sizeof(*gp)); - - if (gp->tx_bip_fem_auto_detect) - answer = true; - - ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); - if (ret < 0) { - wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); - goto out; - } - - gp->tx_bip_fem_manufacturer = - gen_parms->general_params.tx_bip_fem_manufacturer; - - wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", - answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); - -out: - kfree(gen_parms); - return ret; -} - -int wl128x_cmd_general_parms(struct wl1271 *wl) -{ - struct wl128x_general_parms_cmd *gen_parms; - struct wl128x_ini_general_params *gp = - &((struct wl128x_nvs_file *)wl->nvs)->general_params; + struct wl1271_ini_general_params *gp = &wl->nvs->general_params; bool answer = false; int ret; @@ -187,9 +147,8 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) int wl1271_cmd_radio_parms(struct wl1271 *wl) { - struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; struct wl1271_radio_parms_cmd *radio_parms; - struct wl1271_ini_general_params *gp = &nvs->general_params; + struct wl1271_ini_general_params *gp = &wl->nvs->general_params; int ret; if (!wl->nvs) @@ -202,18 +161,18 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; /* 2.4GHz parameters */ - memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, + memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, sizeof(struct wl1271_ini_band_params_2)); memcpy(&radio_parms->dyn_params_2, - &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + &wl->nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, sizeof(struct wl1271_ini_fem_params_2)); /* 5GHz parameters */ memcpy(&radio_parms->static_params_5, - &nvs->stat_radio_params_5, + &wl->nvs->stat_radio_params_5, sizeof(struct wl1271_ini_band_params_5)); memcpy(&radio_parms->dyn_params_5, - &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + &wl->nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, sizeof(struct wl1271_ini_fem_params_5)); wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", @@ -227,50 +186,6 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) return ret; } -int wl128x_cmd_radio_parms(struct wl1271 *wl) -{ - struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; - struct wl128x_radio_parms_cmd *radio_parms; - struct wl128x_ini_general_params *gp = &nvs->general_params; - int ret; - - if (!wl->nvs) - return -ENODEV; - - radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); - if (!radio_parms) - return -ENOMEM; - - radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; - - /* 2.4GHz parameters */ - memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, - sizeof(struct wl128x_ini_band_params_2)); - memcpy(&radio_parms->dyn_params_2, - &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl128x_ini_fem_params_2)); - - /* 5GHz parameters */ - memcpy(&radio_parms->static_params_5, - &nvs->stat_radio_params_5, - sizeof(struct wl128x_ini_band_params_5)); - memcpy(&radio_parms->dyn_params_5, - &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl128x_ini_fem_params_5)); - - radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; - - wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", - radio_parms, sizeof(*radio_parms)); - - ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); - if (ret < 0) - wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); - - kfree(radio_parms); - return ret; -} - int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) { struct wl1271_ext_radio_parms_cmd *ext_radio_parms; @@ -1070,7 +985,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl) memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); - cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); + cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); cmd->bss_index = WL1271_AP_BSS_INDEX; cmd->global_hlid = WL1271_AP_GLOBAL_HLID; cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.h b/trunk/drivers/net/wireless/wl12xx/cmd.h index 5cac95d9480c..54c12e71417e 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.h +++ b/trunk/drivers/net/wireless/wl12xx/cmd.h @@ -32,9 +32,7 @@ struct acx_header; int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, size_t res_len); int wl1271_cmd_general_parms(struct wl1271 *wl); -int wl128x_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); -int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); @@ -417,21 +415,6 @@ struct wl1271_general_parms_cmd { u8 padding[3]; } __packed; -struct wl128x_general_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - struct wl128x_ini_general_params general_params; - - u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; - u8 sr_sen_n_p; - u8 sr_sen_n_p_gain; - u8 sr_sen_nrn; - u8 sr_sen_prn; - u8 padding[3]; -} __packed; - struct wl1271_radio_parms_cmd { struct wl1271_cmd_header header; @@ -448,23 +431,6 @@ struct wl1271_radio_parms_cmd { u8 padding3[2]; } __packed; -struct wl128x_radio_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - /* Static radio parameters */ - struct wl128x_ini_band_params_2 static_params_2; - struct wl128x_ini_band_params_5 static_params_5; - - u8 fem_vendor_and_options; - - /* Dynamic radio parameters */ - struct wl128x_ini_fem_params_2 dyn_params_2; - u8 padding2; - struct wl128x_ini_fem_params_5 dyn_params_5; -} __packed; - struct wl1271_ext_radio_parms_cmd { struct wl1271_cmd_header header; diff --git a/trunk/drivers/net/wireless/wl12xx/conf.h b/trunk/drivers/net/wireless/wl12xx/conf.h index d16094f2604f..856a8a2fff4f 100644 --- a/trunk/drivers/net/wireless/wl12xx/conf.h +++ b/trunk/drivers/net/wireless/wl12xx/conf.h @@ -683,18 +683,10 @@ struct conf_tx_settings { struct conf_tx_rate_class ap_bcst_conf; /* - * Allow this number of TX retries to a connected station/AP before an + * AP-mode - allow this number of TX retries to a station before an * event is triggered from FW. - * In AP-mode the hlids of unreachable stations are given in the - * "sta_tx_retry_exceeded" member in the event mailbox. */ - u8 max_tx_retries; - - /* - * AP-mode - after this number of seconds a connected station is - * considered inactive. - */ - u16 ap_aging_period; + u16 ap_max_tx_retries; /* * Configuration for TID parameters. @@ -1012,9 +1004,7 @@ enum { CONF_REF_CLK_19_2_E, CONF_REF_CLK_26_E, CONF_REF_CLK_38_4_E, - CONF_REF_CLK_52_E, - CONF_REF_CLK_38_4_M_XTAL, - CONF_REF_CLK_26_M_XTAL, + CONF_REF_CLK_52_E }; enum single_dual_band_enum { @@ -1028,6 +1018,15 @@ enum single_dual_band_enum { #define CONF_NUMBER_OF_CHANNELS_2_4 14 #define CONF_NUMBER_OF_CHANNELS_5 35 +struct conf_radio_parms { + /* + * FEM parameter set to use + * + * Range: 0 or 1 + */ + u8 fem; +}; + struct conf_itrim_settings { /* enable dco itrim */ u8 enable; @@ -1203,9 +1202,7 @@ struct conf_drv_settings { struct conf_scan_settings scan; struct conf_rf_settings rf; struct conf_ht_setting ht; - struct conf_memory_settings mem_wl127x; - struct conf_memory_settings mem_wl128x; - u8 hci_io_ds; + struct conf_memory_settings mem; }; #endif diff --git a/trunk/drivers/net/wireless/wl12xx/debugfs.c b/trunk/drivers/net/wireless/wl12xx/debugfs.c index 70ab1986788e..8e75b09723b9 100644 --- a/trunk/drivers/net/wireless/wl12xx/debugfs.c +++ b/trunk/drivers/net/wireless/wl12xx/debugfs.c @@ -267,7 +267,7 @@ static ssize_t gpio_power_write(struct file *file, } buf[len] = '\0'; - ret = kstrtoul(buf, 0, &value); + ret = strict_strtoul(buf, 0, &value); if (ret < 0) { wl1271_warning("illegal value in gpio_power"); return -EINVAL; diff --git a/trunk/drivers/net/wireless/wl12xx/event.c b/trunk/drivers/net/wireless/wl12xx/event.c index d7be3aec6fc3..1b170c5cc595 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.c +++ b/trunk/drivers/net/wireless/wl12xx/event.c @@ -33,7 +33,6 @@ void wl1271_pspoll_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; - int ret; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, pspoll_work); @@ -56,13 +55,8 @@ void wl1271_pspoll_work(struct work_struct *work) * delivery failure occurred, and no-one changed state since, so * we should go back to powersave. */ - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); - wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }; @@ -135,6 +129,11 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, true); + if (ret < 0) + break; + + /* go to extremely low power mode */ + wl1271_ps_elp_sleep(wl); break; default: break; @@ -174,8 +173,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) u32 vector; bool beacon_loss = false; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); - bool disconnect_sta = false; - unsigned long sta_bitmap = 0; wl1271_event_mbox_dump(mbox); @@ -231,60 +228,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_event_rssi_trigger(wl, mbox); } - if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { - wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); - if (wl->vif) - wl1271_tx_dummy_packet(wl); - } - - /* - * "TX retries exceeded" has a different meaning according to mode. - * In AP mode the offending station is disconnected. In STA mode we - * report connection loss. - */ - if (vector & MAX_TX_RETRY_EVENT_ID) { - wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); - if (is_ap) { - sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); - disconnect_sta = true; - } else { - beacon_loss = true; - } - } - - if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { - wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); - sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); - disconnect_sta = true; - } - if (wl->vif && beacon_loss) ieee80211_connection_loss(wl->vif); - if (is_ap && disconnect_sta) { - u32 num_packets = wl->conf.tx.max_tx_retries; - struct ieee80211_sta *sta; - const u8 *addr; - int h; - - for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); - h < AP_MAX_LINKS; - h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { - if (!wl1271_is_active_sta(wl, h)) - continue; - - addr = wl->links[h].addr; - - rcu_read_lock(); - sta = ieee80211_find_sta(wl->vif, addr); - if (sta) { - wl1271_debug(DEBUG_EVENT, "remove sta %d", h); - ieee80211_report_low_ack(sta, num_packets); - } - rcu_read_unlock(); - } - } - return 0; } diff --git a/trunk/drivers/net/wireless/wl12xx/event.h b/trunk/drivers/net/wireless/wl12xx/event.h index 7ae5a0821241..0e80886f3031 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.h +++ b/trunk/drivers/net/wireless/wl12xx/event.h @@ -58,16 +58,10 @@ enum { CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), - MAX_TX_RETRY_EVENT_ID = BIT(20), - /* STA: dummy paket for dynamic mem blocks */ - DUMMY_PACKET_EVENT_ID = BIT(21), - /* AP: STA remove complete */ - STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), + ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), + STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */ SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), - /* STA: SG prediction */ SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), - /* AP: Inactive STA */ - INACTIVE_STA_EVENT_ID = BIT(23), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), DBG_EVENT_ID = BIT(26), @@ -122,11 +116,7 @@ struct event_mailbox { /* AP FW only */ u8 hlid_removed; - - /* a bitmap of hlids for stations that have been inactive too long */ __le16 sta_aging_status; - - /* a bitmap of hlids for stations which didn't respond to TX */ __le16 sta_tx_retry_exceeded; u8 reserved_5[24]; @@ -137,7 +127,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl); int wl1271_event_handle(struct wl1271 *wl, u8 mbox); void wl1271_pspoll_work(struct work_struct *work); -/* Functions from main.c */ -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); - #endif diff --git a/trunk/drivers/net/wireless/wl12xx/ini.h b/trunk/drivers/net/wireless/wl12xx/ini.h index 1420c842b8f1..c330a2583dfd 100644 --- a/trunk/drivers/net/wireless/wl12xx/ini.h +++ b/trunk/drivers/net/wireless/wl12xx/ini.h @@ -41,28 +41,6 @@ struct wl1271_ini_general_params { u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; } __packed; -#define WL128X_INI_MAX_SETTINGS_PARAM 4 - -struct wl128x_ini_general_params { - u8 ref_clock; - u8 settling_time; - u8 clk_valid_on_wakeup; - u8 tcxo_ref_clock; - u8 tcxo_settling_time; - u8 tcxo_valid_on_wakeup; - u8 tcxo_ldo_voltage; - u8 xtal_itrim_val; - u8 platform_conf; - u8 dual_mode_select; - u8 tx_bip_fem_auto_detect; - u8 tx_bip_fem_manufacturer; - u8 general_settings[WL128X_INI_MAX_SETTINGS_PARAM]; - u8 sr_state; - u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM]; - u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM]; - u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; -} __packed; - #define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15 struct wl1271_ini_band_params_2 { @@ -71,15 +49,8 @@ struct wl1271_ini_band_params_2 { u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; } __packed; -#define WL1271_INI_CHANNEL_COUNT_2 14 - -struct wl128x_ini_band_params_2 { - u8 rx_trace_insertion_loss; - u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_2]; - u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; -} __packed; - #define WL1271_INI_RATE_GROUP_COUNT 6 +#define WL1271_INI_CHANNEL_COUNT_2 14 struct wl1271_ini_fem_params_2 { __le16 tx_bip_ref_pd_voltage; @@ -97,28 +68,6 @@ struct wl1271_ini_fem_params_2 { u8 normal_to_degraded_high_thr; } __packed; -#define WL128X_INI_RATE_GROUP_COUNT 7 -/* low and high temperatures */ -#define WL128X_INI_PD_VS_TEMPERATURE_RANGES 2 - -struct wl128x_ini_fem_params_2 { - __le16 tx_bip_ref_pd_voltage; - u8 tx_bip_ref_power; - u8 tx_bip_ref_offset; - u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2]; - u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2]; - u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT + 1]; - u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_2]; - u8 tx_pd_vs_temperature[WL128X_INI_PD_VS_TEMPERATURE_RANGES]; - u8 rx_fem_insertion_loss; - u8 degraded_low_to_normal_thr; - u8 normal_to_degraded_high_thr; -} __packed; - #define WL1271_INI_CHANNEL_COUNT_5 35 #define WL1271_INI_SUB_BAND_COUNT_5 7 @@ -128,12 +77,6 @@ struct wl1271_ini_band_params_5 { u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; } __packed; -struct wl128x_ini_band_params_5 { - u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; - u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_5]; - u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; -} __packed; - struct wl1271_ini_fem_params_5 { __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; @@ -149,23 +92,6 @@ struct wl1271_ini_fem_params_5 { u8 normal_to_degraded_high_thr; } __packed; -struct wl128x_ini_fem_params_5 { - __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; - u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; - u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5]; - u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5]; - u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT]; - u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_5]; - u8 tx_pd_vs_temperature[WL1271_INI_SUB_BAND_COUNT_5 * - WL128X_INI_PD_VS_TEMPERATURE_RANGES]; - u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; - u8 degraded_low_to_normal_thr; - u8 normal_to_degraded_high_thr; -} __packed; /* NVS data structure */ #define WL1271_INI_NVS_SECTION_SIZE 468 @@ -174,7 +100,7 @@ struct wl128x_ini_fem_params_5 { #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 struct wl1271_nvs_file { - /* NVS section - must be first! */ + /* NVS section */ u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; /* INI section */ @@ -194,24 +120,4 @@ struct wl1271_nvs_file { } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; } __packed; -struct wl128x_nvs_file { - /* NVS section - must be first! */ - u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; - - /* INI section */ - struct wl128x_ini_general_params general_params; - u8 fem_vendor_and_options; - struct wl128x_ini_band_params_2 stat_radio_params_2; - u8 padding2; - struct { - struct wl128x_ini_fem_params_2 params; - u8 padding; - } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; - struct wl128x_ini_band_params_5 stat_radio_params_5; - u8 padding3; - struct { - struct wl128x_ini_fem_params_5 params; - u8 padding; - } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; -} __packed; #endif diff --git a/trunk/drivers/net/wireless/wl12xx/init.c b/trunk/drivers/net/wireless/wl12xx/init.c index ab3b1e21de29..6072fe457135 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.c +++ b/trunk/drivers/net/wireless/wl12xx/init.c @@ -31,7 +31,6 @@ #include "cmd.h" #include "reg.h" #include "tx.h" -#include "io.h" int wl1271_sta_init_templates_config(struct wl1271 *wl) { @@ -322,11 +321,9 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) { int ret; - if (wl->chip.id != CHIP_ID_1283_PG20) { - ret = wl1271_cmd_ext_radio_parms(wl); - if (ret < 0) - return ret; - } + ret = wl1271_cmd_ext_radio_parms(wl); + if (ret < 0) + return ret; /* PS config */ ret = wl1271_acx_config_ps(wl); @@ -375,10 +372,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_sta_max_tx_retry(wl); - if (ret < 0) - return ret; - ret = wl1271_acx_sta_mem_cfg(wl); if (ret < 0) return ret; @@ -445,7 +438,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_ap_max_tx_retry(wl); + ret = wl1271_acx_max_tx_retry(wl); if (ret < 0) return ret; @@ -511,27 +504,6 @@ static int wl1271_set_ba_policies(struct wl1271 *wl) return ret; } -int wl1271_chip_specific_init(struct wl1271 *wl) -{ - int ret = 0; - - if (wl->chip.id == CHIP_ID_1283_PG20) { - u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; - - if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) - /* Enable SDIO padding */ - host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; - - /* Must be before wl1271_acx_init_mem_config() */ - ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); - if (ret < 0) - goto out; - } -out: - return ret; -} - - int wl1271_hw_init(struct wl1271 *wl) { struct conf_tx_ac_category *conf_ac; @@ -539,22 +511,11 @@ int wl1271_hw_init(struct wl1271 *wl) int ret, i; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = wl128x_cmd_general_parms(wl); - else - ret = wl1271_cmd_general_parms(wl); - if (ret < 0) - return ret; - - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = wl128x_cmd_radio_parms(wl); - else - ret = wl1271_cmd_radio_parms(wl); + ret = wl1271_cmd_general_parms(wl); if (ret < 0) return ret; - /* Chip-specific init */ - ret = wl1271_chip_specific_init(wl); + ret = wl1271_cmd_radio_parms(wl); if (ret < 0) return ret; diff --git a/trunk/drivers/net/wireless/wl12xx/init.h b/trunk/drivers/net/wireless/wl12xx/init.h index 4975270a91ab..3a8bd3f426d2 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.h +++ b/trunk/drivers/net/wireless/wl12xx/init.h @@ -31,7 +31,6 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl); int wl1271_init_phy_config(struct wl1271 *wl); int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl); -int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/io.c b/trunk/drivers/net/wireless/wl12xx/io.c index da5c1ad942a4..d557f73e7c19 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.c +++ b/trunk/drivers/net/wireless/wl12xx/io.c @@ -29,7 +29,6 @@ #include "wl12xx.h" #include "wl12xx_80211.h" #include "io.h" -#include "tx.h" #define OCP_CMD_LOOP 32 @@ -44,16 +43,6 @@ #define OCP_STATUS_REQ_FAILED 0x20000 #define OCP_STATUS_RESP_ERROR 0x30000 -bool wl1271_set_block_size(struct wl1271 *wl) -{ - if (wl->if_ops->set_block_size) { - wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE); - return true; - } - - return false; -} - void wl1271_disable_interrupts(struct wl1271 *wl) { wl->if_ops->disable_irq(wl); diff --git a/trunk/drivers/net/wireless/wl12xx/io.h b/trunk/drivers/net/wireless/wl12xx/io.h index 36e185583ec4..c1aac8292089 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.h +++ b/trunk/drivers/net/wireless/wl12xx/io.h @@ -169,8 +169,5 @@ int wl1271_init_ieee80211(struct wl1271 *wl); struct ieee80211_hw *wl1271_alloc_hw(void); int wl1271_free_hw(struct wl1271 *wl); irqreturn_t wl1271_irq(int irq, void *data); -bool wl1271_set_block_size(struct wl1271 *wl); -int wl1271_tx_dummy_packet(struct wl1271 *wl); -void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index 0c69e959d0de..8b3c8d196b03 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "wl12xx.h" #include "wl12xx_80211.h" @@ -55,7 +54,7 @@ static struct conf_drv_settings default_conf = { [CONF_SG_BT_PER_THRESHOLD] = 7500, [CONF_SG_HV3_MAX_OVERRIDE] = 0, [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, - [CONF_SG_BT_LOAD_RATIO] = 200, + [CONF_SG_BT_LOAD_RATIO] = 50, [CONF_SG_AUTO_PS_MODE] = 1, [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, @@ -192,8 +191,7 @@ static struct conf_drv_settings default_conf = { .long_retry_limit = 10, .aflags = 0, }, - .max_tx_retries = 100, - .ap_aging_period = 300, + .ap_max_tx_retries = 100, .tid_conf_count = 4, .tid_conf = { [CONF_TX_AC_BE] = { @@ -256,7 +254,7 @@ static struct conf_drv_settings default_conf = { .ps_poll_threshold = 10, .ps_poll_recovery_period = 700, .bet_enable = CONF_BET_MODE_ENABLE, - .bet_max_consecutive = 50, + .bet_max_consecutive = 10, .psm_entry_retries = 5, .psm_exit_retries = 255, .psm_entry_nullfunc_retries = 3, @@ -300,7 +298,7 @@ static struct conf_drv_settings default_conf = { .tx_ba_win_size = 64, .inactivity_timeout = 10000, }, - .mem_wl127x = { + .mem = { .num_stations = 1, .ssid_profiles = 1, .rx_block_num = 70, @@ -309,18 +307,7 @@ static struct conf_drv_settings default_conf = { .min_req_tx_blocks = 100, .min_req_rx_blocks = 22, .tx_min = 27, - }, - .mem_wl128x = { - .num_stations = 1, - .ssid_profiles = 1, - .rx_block_num = 40, - .tx_min_block_num = 40, - .dynamic_memory = 1, - .min_req_tx_blocks = 45, - .min_req_rx_blocks = 22, - .tx_min = 27, - }, - .hci_io_ds = HCI_IO_DS_6MA, + } }; static void __wl1271_op_remove_interface(struct wl1271 *wl); @@ -342,7 +329,6 @@ static struct platform_device wl1271_device = { }, }; -static DEFINE_MUTEX(wl_list_mutex); static LIST_HEAD(wl_list); static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, @@ -373,12 +359,10 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, return NOTIFY_DONE; wl_temp = hw->priv; - mutex_lock(&wl_list_mutex); list_for_each_entry(wl, &wl_list, list) { if (wl == wl_temp) break; } - mutex_unlock(&wl_list_mutex); if (wl != wl_temp) return NOTIFY_DONE; @@ -454,30 +438,15 @@ static int wl1271_plt_init(struct wl1271 *wl) struct conf_tx_tid *conf_tid; int ret, i; - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = wl128x_cmd_general_parms(wl); - else - ret = wl1271_cmd_general_parms(wl); + ret = wl1271_cmd_general_parms(wl); if (ret < 0) return ret; - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = wl128x_cmd_radio_parms(wl); - else - ret = wl1271_cmd_radio_parms(wl); - if (ret < 0) - return ret; - - if (wl->chip.id != CHIP_ID_1283_PG20) { - ret = wl1271_cmd_ext_radio_parms(wl); - if (ret < 0) - return ret; - } + ret = wl1271_cmd_radio_parms(wl); if (ret < 0) return ret; - /* Chip-specific initializations */ - ret = wl1271_chip_specific_init(wl); + ret = wl1271_cmd_ext_radio_parms(wl); if (ret < 0) return ret; @@ -624,17 +593,15 @@ static void wl1271_fw_status(struct wl1271 *wl, { struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; - u32 old_tx_blk_count = wl->tx_blocks_available; - u32 freed_blocks = 0; + u32 total = 0; int i; - if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (wl->bss_type == BSS_TYPE_AP_BSS) wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(struct wl1271_fw_ap_status), false); - } else { + else wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(struct wl1271_fw_sta_status), false); - } wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", @@ -645,38 +612,23 @@ static void wl1271_fw_status(struct wl1271 *wl, /* update number of available TX blocks */ for (i = 0; i < NUM_TX_QUEUES; i++) { - freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - - wl->tx_blocks_freed[i]; + u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - + wl->tx_blocks_freed[i]; wl->tx_blocks_freed[i] = le32_to_cpu(status->tx_released_blks[i]); - } - - wl->tx_allocated_blocks -= freed_blocks; - - if (wl->bss_type == BSS_TYPE_AP_BSS) { - /* Update num of allocated TX blocks per link and ps status */ - wl1271_irq_update_links_status(wl, &full_status->ap); - wl->tx_blocks_available += freed_blocks; - } else { - int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; - - /* - * The FW might change the total number of TX memblocks before - * we get a notification about blocks being released. Thus, the - * available blocks calculation might yield a temporary result - * which is lower than the actual available blocks. Keeping in - * mind that only blocks that were allocated can be moved from - * TX to RX, tx_blocks_available should never decrease here. - */ - wl->tx_blocks_available = max((int)wl->tx_blocks_available, - avail); + wl->tx_blocks_available += cnt; + total += cnt; } /* if more blocks are available now, tx work can be scheduled */ - if (wl->tx_blocks_available > old_tx_blk_count) + if (total) clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); + /* for AP update num of allocated TX blocks per link and ps status */ + if (wl->bss_type == BSS_TYPE_AP_BSS) + wl1271_irq_update_links_status(wl, &full_status->ap); + /* update the host-chipset time offset */ getnstimeofday(&ts); wl->time_offset = (timespec_to_ns(&ts) >> 10) - @@ -722,13 +674,6 @@ irqreturn_t wl1271_irq(int irq, void *cookie) set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); cancel_work_sync(&wl->tx_work); - /* - * In case edge triggered interrupt must be used, we cannot iterate - * more than once without introducing race conditions with the hardirq. - */ - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) - loopcount = 1; - mutex_lock(&wl->mutex); wl1271_debug(DEBUG_IRQ, "IRQ work"); @@ -840,17 +785,11 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) switch (wl->bss_type) { case BSS_TYPE_AP_BSS: - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_AP_FW_NAME; - else - fw_name = WL127X_AP_FW_NAME; + fw_name = WL1271_AP_FW_NAME; break; case BSS_TYPE_IBSS: case BSS_TYPE_STA_BSS: - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_FW_NAME; - else - fw_name = WL1271_FW_NAME; + fw_name = WL1271_FW_NAME; break; default: wl1271_error("no compatible firmware for bss_type %d", @@ -899,14 +838,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get nvs file: %d", ret); return ret; } - wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); @@ -1015,17 +954,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) if (ret < 0) goto out; break; - case CHIP_ID_1283_PG20: - wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", - wl->chip.id); - - ret = wl1271_setup(wl); - if (ret < 0) - goto out; - if (wl1271_set_block_size(wl)) - wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; - break; - case CHIP_ID_1283_PG10: default: wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); ret = -ENODEV; @@ -1050,24 +978,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) return ret; } -static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl) -{ - unsigned int quirks = 0; - unsigned int *fw_ver = wl->chip.fw_ver; - - /* Only for wl127x */ - if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && - /* Check STA version */ - (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && - (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || - /* Check AP version */ - ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && - (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) - quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; - - return quirks; -} - int wl1271_plt_start(struct wl1271 *wl) { int retries = WL1271_BOOT_RETRIES; @@ -1103,9 +1013,6 @@ int wl1271_plt_start(struct wl1271 *wl) wl->state = WL1271_STATE_PLT; wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver_str); - - /* Check if any quirks are needed with older fw versions */ - wl->quirks |= wl1271_get_fw_ver_quirks(wl); goto out; irq_disable: @@ -1133,7 +1040,7 @@ int wl1271_plt_start(struct wl1271 *wl) return ret; } -static int __wl1271_plt_stop(struct wl1271 *wl) +int __wl1271_plt_stop(struct wl1271 *wl) { int ret = 0; @@ -1217,69 +1124,6 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) spin_unlock_irqrestore(&wl->wl_lock, flags); } -int wl1271_tx_dummy_packet(struct wl1271 *wl) -{ - unsigned long flags; - - spin_lock_irqsave(&wl->wl_lock, flags); - set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); - wl->tx_queue_count++; - spin_unlock_irqrestore(&wl->wl_lock, flags); - - /* The FW is low on RX memory blocks, so send the dummy packet asap */ - if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) - wl1271_tx_work_locked(wl); - - /* - * If the FW TX is busy, TX work will be scheduled by the threaded - * interrupt handler function - */ - return 0; -} - -/* - * The size of the dummy packet should be at least 1400 bytes. However, in - * order to minimize the number of bus transactions, aligning it to 512 bytes - * boundaries could be beneficial, performance wise - */ -#define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512)) - -static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) -{ - struct sk_buff *skb; - struct ieee80211_hdr_3addr *hdr; - unsigned int dummy_packet_size; - - dummy_packet_size = TOTAL_TX_DUMMY_PACKET_SIZE - - sizeof(struct wl1271_tx_hw_descr) - sizeof(*hdr); - - skb = dev_alloc_skb(TOTAL_TX_DUMMY_PACKET_SIZE); - if (!skb) { - wl1271_warning("Failed to allocate a dummy packet skb"); - return NULL; - } - - skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); - - hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); - memset(hdr, 0, sizeof(*hdr)); - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - - memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size); - - /* Dummy packets require the TID to be management */ - skb->priority = WL1271_TID_MGMT; - - /* Initialize all fields that might be used */ - skb->queue_mapping = 0; - memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); - - return skb; -} - - static struct notifier_block wl1271_dev_notifier = { .notifier_call = wl1271_dev_notify, }; @@ -1330,16 +1174,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - /* - * in some very corner case HW recovery scenarios its possible to - * get here before __wl1271_op_remove_interface is complete, so - * opt out if that is the case. - */ - if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { - ret = -EBUSY; - goto out; - } - switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; @@ -1408,7 +1242,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wl->vif = vif; wl->state = WL1271_STATE_ON; - set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); /* update hw/fw version info in wiphy struct */ @@ -1416,9 +1249,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, strncpy(wiphy->fw_version, wl->chip.fw_ver_str, sizeof(wiphy->fw_version)); - /* Check if any quirks are needed with older fw versions */ - wl->quirks |= wl1271_get_fw_ver_quirks(wl); - /* * Now we know if 11a is supported (info from the NVS), so disable * 11a channels if not supported @@ -1432,10 +1262,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, out: mutex_unlock(&wl->mutex); - mutex_lock(&wl_list_mutex); if (!ret) list_add(&wl->list, &wl_list); - mutex_unlock(&wl_list_mutex); return ret; } @@ -1446,15 +1274,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); - /* because of hardware recovery, we may get here twice */ - if (wl->state != WL1271_STATE_ON) - return; - wl1271_info("down"); - mutex_lock(&wl_list_mutex); list_del(&wl->list); - mutex_unlock(&wl_list_mutex); + + WARN_ON(wl->state != WL1271_STATE_ON); /* enable dyn ps just in case (if left on due to fw crash etc) */ if (wl->bss_type == BSS_TYPE_STA_BSS) @@ -1462,15 +1286,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { wl->scan.state = WL1271_SCAN_STATE_IDLE; - memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); + kfree(wl->scan.scanned_ch); + wl->scan.scanned_ch = NULL; wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); } - /* - * this must be before the cancel_work calls below, so that the work - * functions don't perform further work. - */ wl->state = WL1271_STATE_OFF; mutex_unlock(&wl->mutex); @@ -1500,7 +1321,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; - wl->tx_allocated_blocks = 0; wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->tx_security_last_seq = 0; @@ -1508,6 +1328,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->time_offset = 0; wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->flags = 0; wl->vif = NULL; wl->filters = 0; wl1271_free_ap_keys(wl); @@ -1515,13 +1336,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; - /* - * this is performed after the cancel_work calls and the associated - * mutex_lock, so that wl1271_op_add_interface does not accidentally - * get executed before all these vars have been reset. - */ - wl->flags = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; @@ -1554,7 +1368,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->recovery_work); } -void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) +static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) { wl1271_set_default_filters(wl); @@ -1617,10 +1431,10 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) * One of the side effects of the JOIN command is that is clears * WPA/WPA2 keys from the chipset. Performing a JOIN while associated * to a WPA/WPA2 access point will therefore kill the data-path. - * Currently the only valid scenario for JOIN during association - * is on roaming, in which case we will also be given new keys. - * Keep the below message for now, unless it starts bothering - * users who really like to roam a lot :) + * Currently there is no supported scenario for JOIN during + * association - if it becomes a supported scenario, the WPA/WPA2 keys + * must be handled somehow. + * */ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) wl1271_info("JOIN while associated."); @@ -1676,7 +1490,7 @@ static int wl1271_unjoin(struct wl1271 *wl) clear_bit(WL1271_FLAG_JOINED, &wl->flags); memset(wl->bssid, 0, ETH_ALEN); - /* stop filtering packets based on bssid */ + /* stop filterting packets based on bssid */ wl1271_configure_filters(wl, FIF_OTHER_BSS); out: @@ -1755,12 +1569,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) { - /* we support configuring the channel and band while off */ - if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - wl->band = conf->channel->band; - wl->channel = channel; - } - + ret = -EAGAIN; goto out; } @@ -2841,31 +2650,32 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; conf_tid->apsd_conf[0] = 0; conf_tid->apsd_conf[1] = 0; - goto out; - } - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; + } else { + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; - /* - * the txop is confed in units of 32us by the mac80211, - * we need us - */ - ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), - params->cw_min, params->cw_max, - params->aifs, params->txop << 5); - if (ret < 0) - goto out_sleep; + /* + * the txop is confed in units of 32us by the mac80211, + * we need us + */ + ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), + params->cw_min, params->cw_max, + params->aifs, params->txop << 5); + if (ret < 0) + goto out_sleep; - ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), - CONF_CHANNEL_TYPE_EDCF, - wl1271_tx_get_queue(queue), - ps_scheme, CONF_ACK_POLICY_LEGACY, - 0, 0); + ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), + CONF_CHANNEL_TYPE_EDCF, + wl1271_tx_get_queue(queue), + ps_scheme, CONF_ACK_POLICY_LEGACY, + 0, 0); + if (ret < 0) + goto out_sleep; out_sleep: - wl1271_ps_elp_sleep(wl); + wl1271_ps_elp_sleep(wl); + } out: mutex_unlock(&wl->mutex); @@ -2954,12 +2764,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); } -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) -{ - int id = hlid - WL1271_AP_STA_HLID_START; - return test_bit(id, wl->ap_hlid_map); -} - static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -3043,11 +2847,10 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, return ret; } -static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) +int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size) { struct wl1271 *wl = hw->priv; int ret; @@ -3200,8 +3003,7 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { #ifdef CONFIG_WL12XX_HT #define WL12XX_HT_CAP { \ - .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ - (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ + .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ .ht_supported = true, \ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ @@ -3405,7 +3207,8 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, unsigned long res; int ret; - ret = kstrtoul(buf, 10, &res); + ret = strict_strtoul(buf, 10, &res); + if (ret < 0) { wl1271_warning("incorrect value written to bt_coex_mode"); return count; @@ -3470,11 +3273,7 @@ int wl1271_register_hw(struct wl1271 *wl) ret = wl1271_fetch_nvs(wl); if (ret == 0) { - /* NOTE: The wl->nvs->nvs element must be first, in - * order to simplify the casting, we assume it is at - * the beginning of the wl->nvs structure. - */ - u8 *nvs_ptr = (u8 *)wl->nvs; + u8 *nvs_ptr = (u8 *)wl->nvs->nvs; wl->mac_addr[0] = nvs_ptr[11]; wl->mac_addr[1] = nvs_ptr[10]; @@ -3542,6 +3341,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_CONNECTION_MONITOR | IEEE80211_HW_SUPPORTS_CQM_RSSI | + IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_AP_LINK_PS; wl->hw->wiphy->cipher_suites = cipher_suites; @@ -3558,10 +3358,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - sizeof(struct ieee80211_header); - /* make sure all our channels fit in the scanned_ch bitmask */ - BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + - ARRAY_SIZE(wl1271_channels_5ghz) > - WL1271_MAX_CHANNELS); /* * We keep local copies of the band structs because we need to * modify them on a per-device basis. @@ -3662,7 +3458,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; - wl->platform_quirks = 0; memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) @@ -3683,17 +3478,11 @@ struct ieee80211_hw *wl1271_alloc_hw(void) goto err_hw; } - wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); - if (!wl->dummy_packet) { - ret = -ENOMEM; - goto err_aggr; - } - /* Register platform device */ ret = platform_device_register(wl->plat_dev); if (ret) { wl1271_error("couldn't register platform device"); - goto err_dummy_packet; + goto err_aggr; } dev_set_drvdata(&wl->plat_dev->dev, wl); @@ -3719,9 +3508,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) err_platform: platform_device_unregister(wl->plat_dev); -err_dummy_packet: - dev_kfree_skb(wl->dummy_packet); - err_aggr: free_pages((unsigned long)wl->aggr_buf, order); @@ -3741,7 +3527,6 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw); int wl1271_free_hw(struct wl1271 *wl) { platform_device_unregister(wl->plat_dev); - dev_kfree_skb(wl->dummy_packet); free_pages((unsigned long)wl->aggr_buf, get_order(WL1271_AGGR_BUFFER_SIZE)); kfree(wl->plat_dev); diff --git a/trunk/drivers/net/wireless/wl12xx/ps.c b/trunk/drivers/net/wireless/wl12xx/ps.c index b8deada5d020..971f13e792da 100644 --- a/trunk/drivers/net/wireless/wl12xx/ps.c +++ b/trunk/drivers/net/wireless/wl12xx/ps.c @@ -149,6 +149,9 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, case STATION_ACTIVE_MODE: default: wl1271_debug(DEBUG_PSM, "leaving psm"); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + return ret; /* disable beacon early termination */ ret = wl1271_acx_bet_enable(wl, false); diff --git a/trunk/drivers/net/wireless/wl12xx/reg.h b/trunk/drivers/net/wireless/wl12xx/reg.h index 440a4ee9cb42..990960771528 100644 --- a/trunk/drivers/net/wireless/wl12xx/reg.h +++ b/trunk/drivers/net/wireless/wl12xx/reg.h @@ -207,8 +207,6 @@ #define CHIP_ID_1271_PG10 (0x4030101) #define CHIP_ID_1271_PG20 (0x4030111) -#define CHIP_ID_1283_PG10 (0x05030101) -#define CHIP_ID_1283_PG20 (0x05030111) #define ENABLE (REGISTERS_BASE + 0x5450) @@ -454,11 +452,24 @@ #define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 #define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 +/* + * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile + * for platforms using active high interrupt level + */ +#ifdef USE_ACTIVE_HIGH #define HI_CFG_DEF_VAL \ (HI_CFG_UART_ENABLE | \ HI_CFG_RST232_ENABLE | \ HI_CFG_CLOCK_REQ_SELECT | \ HI_CFG_HOST_INT_ENABLE) +#else +#define HI_CFG_DEF_VAL \ + (HI_CFG_UART_ENABLE | \ + HI_CFG_RST232_ENABLE | \ + HI_CFG_CLOCK_REQ_SELECT | \ + HI_CFG_HOST_INT_ENABLE) + +#endif #define REF_FREQ_19_2 0 #define REF_FREQ_26_0 1 diff --git a/trunk/drivers/net/wireless/wl12xx/rx.c b/trunk/drivers/net/wireless/wl12xx/rx.c index 2a581495d5c9..919b59f00301 100644 --- a/trunk/drivers/net/wireless/wl12xx/rx.c +++ b/trunk/drivers/net/wireless/wl12xx/rx.c @@ -48,14 +48,18 @@ static void wl1271_rx_status(struct wl1271 *wl, struct ieee80211_rx_status *status, u8 beacon) { + enum ieee80211_band desc_band; + memset(status, 0, sizeof(struct ieee80211_rx_status)); + status->band = wl->band; + if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) - status->band = IEEE80211_BAND_2GHZ; + desc_band = IEEE80211_BAND_2GHZ; else - status->band = IEEE80211_BAND_5GHZ; + desc_band = IEEE80211_BAND_5GHZ; - status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band); + status->rate_idx = wl1271_rate_to_idx(desc->rate, desc_band); #ifdef CONFIG_WL12XX_HT /* 11n support */ @@ -72,8 +76,7 @@ static void wl1271_rx_status(struct wl1271 *wl, */ wl->noise = desc->rssi - (desc->snr >> 1); - status->freq = ieee80211_channel_to_frequency(desc->channel, - status->band); + status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band); if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; @@ -160,25 +163,18 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) break; } - if (wl->chip.id != CHIP_ID_1283_PG20) { - /* - * Choose the block we want to read - * For aggregated packets, only the first memory block - * should be retrieved. The FW takes care of the rest. - */ - mem_block = wl1271_rx_get_mem_block(status, - drv_rx_counter); - - wl->rx_mem_pool_addr.addr = (mem_block << 8) + - le32_to_cpu(wl_mem_map->packet_memory_pool_start); - - wl->rx_mem_pool_addr.addr_extra = - wl->rx_mem_pool_addr.addr + 4; - - wl1271_write(wl, WL1271_SLV_REG_DATA, - &wl->rx_mem_pool_addr, - sizeof(wl->rx_mem_pool_addr), false); - } + /* + * Choose the block we want to read + * For aggregated packets, only the first memory block should + * be retrieved. The FW takes care of the rest. + */ + mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); + wl->rx_mem_pool_addr.addr = (mem_block << 8) + + le32_to_cpu(wl_mem_map->packet_memory_pool_start); + wl->rx_mem_pool_addr.addr_extra = + wl->rx_mem_pool_addr.addr + 4; + wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, + sizeof(wl->rx_mem_pool_addr), false); /* Read all available packets at once */ wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, diff --git a/trunk/drivers/net/wireless/wl12xx/scan.c b/trunk/drivers/net/wireless/wl12xx/scan.c index 5d0544c8f3f5..420653a2859c 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.c +++ b/trunk/drivers/net/wireless/wl12xx/scan.c @@ -48,7 +48,8 @@ void wl1271_scan_complete_work(struct work_struct *work) goto out; wl->scan.state = WL1271_SCAN_STATE_IDLE; - memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); + kfree(wl->scan.scanned_ch); + wl->scan.scanned_ch = NULL; wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, false); @@ -86,7 +87,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, flags = req->channels[i]->flags; - if (!test_bit(i, wl->scan.scanned_ch) && + if (!wl->scan.scanned_ch[i] && !(flags & IEEE80211_CHAN_DISABLED) && ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && (req->channels[i]->band == band)) { @@ -123,7 +124,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, memset(&channels[j].bssid_msb, 0xff, 2); /* Mark the channels we already used */ - set_bit(i, wl->scan.scanned_ch); + wl->scan.scanned_ch[i] = true; j++; } @@ -290,12 +291,6 @@ void wl1271_scan_stm(struct wl1271 *wl) int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req) { - /* - * cfg80211 should guarantee that we don't get more channels - * than what we have registered. - */ - BUG_ON(req->n_channels > WL1271_MAX_CHANNELS); - if (wl->scan.state != WL1271_SCAN_STATE_IDLE) return -EBUSY; @@ -309,8 +304,10 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, } wl->scan.req = req; - memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); + wl->scan.scanned_ch = kcalloc(req->n_channels, + sizeof(*wl->scan.scanned_ch), + GFP_KERNEL); /* we assume failure so that timeout scenarios are handled correctly */ wl->scan.failed = true; ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, diff --git a/trunk/drivers/net/wireless/wl12xx/sdio.c b/trunk/drivers/net/wireless/wl12xx/sdio.c index bcd4ad7ba90d..b1c7d031c391 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio.c @@ -51,13 +51,6 @@ static const struct sdio_device_id wl1271_devices[] = { }; MODULE_DEVICE_TABLE(sdio, wl1271_devices); -static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) -{ - sdio_claim_host(wl->if_priv); - sdio_set_block_size(wl->if_priv, blksz); - sdio_release_host(wl->if_priv); -} - static inline struct sdio_func *wl_to_func(struct wl1271 *wl) { return wl->if_priv; @@ -210,8 +203,7 @@ static struct wl1271_if_operations sdio_ops = { .power = wl1271_sdio_set_power, .dev = wl1271_sdio_wl_to_dev, .enable_irq = wl1271_sdio_enable_interrupts, - .disable_irq = wl1271_sdio_disable_interrupts, - .set_block_size = wl1271_sdio_set_block_size, + .disable_irq = wl1271_sdio_disable_interrupts }; static int __devinit wl1271_probe(struct sdio_func *func, @@ -220,7 +212,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; - unsigned long irqflags; int ret; /* We are only able to handle the wlan function */ @@ -239,9 +230,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - /* Use block mode for transferring over one block size of data */ - func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); @@ -251,16 +239,9 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; - wl->tcxo_clock = wlan_data->board_tcxo_clock; - wl->platform_quirks = wlan_data->platform_quirks; - - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) - irqflags = IRQF_TRIGGER_RISING; - else - irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - irqflags, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); @@ -362,6 +343,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); -MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL127X_AP_FW_NAME); -MODULE_FIRMWARE(WL128X_AP_FW_NAME); +MODULE_FIRMWARE(WL1271_AP_FW_NAME); diff --git a/trunk/drivers/net/wireless/wl12xx/sdio_test.c b/trunk/drivers/net/wireless/wl12xx/sdio_test.c index f28915392877..9fcbd3dd8490 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio_test.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio_test.c @@ -189,12 +189,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) const struct firmware *fw; int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = request_firmware(&fw, WL128X_FW_NAME, - wl1271_wl_to_dev(wl)); - else - ret = request_firmware(&fw, WL1271_FW_NAME, - wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get firmware: %d", ret); @@ -232,14 +227,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { wl1271_error("could not get nvs file: %d", ret); return ret; } - wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); @@ -293,11 +288,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) wl1271_notice("chip id 0x%x (1271 PG20)", wl->chip.id); break; - case CHIP_ID_1283_PG20: - wl1271_notice("chip id 0x%x (1283 PG20)", - wl->chip.id); - break; - case CHIP_ID_1283_PG10: default: wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); return -ENODEV; @@ -417,9 +407,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - /* Use block mode for transferring over one block size of data */ - func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); @@ -429,7 +416,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; - wl->tcxo_clock = wlan_data->board_tcxo_clock; sdio_set_drvdata(func, wl_test); diff --git a/trunk/drivers/net/wireless/wl12xx/spi.c b/trunk/drivers/net/wireless/wl12xx/spi.c index 51662bb68019..ffc745b17f4d 100644 --- a/trunk/drivers/net/wireless/wl12xx/spi.c +++ b/trunk/drivers/net/wireless/wl12xx/spi.c @@ -355,8 +355,7 @@ static struct wl1271_if_operations spi_ops = { .power = wl1271_spi_set_power, .dev = wl1271_spi_wl_to_dev, .enable_irq = wl1271_spi_enable_interrupts, - .disable_irq = wl1271_spi_disable_interrupts, - .set_block_size = NULL, + .disable_irq = wl1271_spi_disable_interrupts }; static int __devinit wl1271_probe(struct spi_device *spi) @@ -364,7 +363,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; - unsigned long irqflags; int ret; pdata = spi->dev.platform_data; @@ -402,13 +400,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) } wl->ref_clock = pdata->board_ref_clock; - wl->tcxo_clock = pdata->board_tcxo_clock; - wl->platform_quirks = pdata->platform_quirks; - - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) - irqflags = IRQF_TRIGGER_RISING; - else - irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; wl->irq = spi->irq; if (wl->irq < 0) { @@ -418,7 +409,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) } ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - irqflags, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); @@ -499,7 +490,5 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL1271_FW_NAME); -MODULE_FIRMWARE(WL128X_FW_NAME); -MODULE_FIRMWARE(WL127X_AP_FW_NAME); -MODULE_FIRMWARE(WL128X_AP_FW_NAME); +MODULE_FIRMWARE(WL1271_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/trunk/drivers/net/wireless/wl12xx/testmode.c b/trunk/drivers/net/wireless/wl12xx/testmode.c index da351d7cd1f2..6ec06a4a4c6d 100644 --- a/trunk/drivers/net/wireless/wl12xx/testmode.c +++ b/trunk/drivers/net/wireless/wl12xx/testmode.c @@ -27,7 +27,6 @@ #include "wl12xx.h" #include "acx.h" -#include "reg.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -205,10 +204,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) kfree(wl->nvs); - if ((wl->chip.id == CHIP_ID_1283_PG20) && - (len != sizeof(struct wl128x_nvs_file))) - return -EINVAL; - else if (len != sizeof(struct wl1271_nvs_file)) + if (len != sizeof(struct wl1271_nvs_file)) return -EINVAL; wl->nvs = kzalloc(len, GFP_KERNEL); diff --git a/trunk/drivers/net/wireless/wl12xx/tx.c b/trunk/drivers/net/wireless/wl12xx/tx.c index 7a3339fd3415..5e9ef7d53e7e 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.c +++ b/trunk/drivers/net/wireless/wl12xx/tx.c @@ -70,28 +70,6 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) } } -static int wl1271_tx_update_filters(struct wl1271 *wl, - struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *)(skb->data + - sizeof(struct wl1271_tx_hw_descr)); - - /* - * stop bssid-based filtering before transmitting authentication - * requests. this way the hw will never drop authentication - * responses coming from BSSIDs it isn't familiar with (e.g. on - * roaming) - */ - if (!ieee80211_is_auth(hdr->frame_control)) - return 0; - - wl1271_configure_filters(wl, FIF_OTHER_BSS); - - return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); -} - static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, struct sk_buff *skb) { @@ -149,29 +127,13 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb) } } -static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, - unsigned int packet_length) -{ - if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) - return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); - else - return ALIGN(packet_length, WL1271_TX_ALIGN_TO); -} - static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 buf_offset, u8 hlid) { struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; - u32 len; u32 total_blocks; int id, ret = -EBUSY; - u32 spare_blocks; - - if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) - spare_blocks = 2; - else - spare_blocks = 1; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; @@ -183,27 +145,17 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, /* approximate the number of blocks required for this packet in the firmware */ - len = wl12xx_calc_packet_alignment(wl, total_len); - - total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + - spare_blocks; - + total_blocks = total_len + TX_HW_BLOCK_SIZE - 1; + total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE; if (total_blocks <= wl->tx_blocks_available) { desc = (struct wl1271_tx_hw_descr *)skb_push( skb, total_len - skb->len); - /* HW descriptor fields change between wl127x and wl128x */ - if (wl->chip.id == CHIP_ID_1283_PG20) { - desc->wl128x_mem.total_mem_blocks = total_blocks; - } else { - desc->wl127x_mem.extra_blocks = spare_blocks; - desc->wl127x_mem.total_mem_blocks = total_blocks; - } - + desc->extra_mem_blocks = TX_HW_BLOCK_SPARE; + desc->total_mem_blocks = total_blocks; desc->id = id; wl->tx_blocks_available -= total_blocks; - wl->tx_allocated_blocks += total_blocks; if (wl->bss_type == BSS_TYPE_AP_BSS) wl->links[hlid].allocated_blks += total_blocks; @@ -220,18 +172,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, return ret; } -static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) -{ - return wl->dummy_packet == skb; -} - static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control, u8 hlid) { struct timespec ts; struct wl1271_tx_hw_descr *desc; - int aligned_len, ac, rate_idx; + int pad, ac, rate_idx; s64 hosttime; u16 tx_attr; @@ -255,25 +202,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); - /* queue */ - ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - desc->tid = skb->priority; + /* configure the tx attributes */ + tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; - if (wl12xx_is_dummy_packet(wl, skb)) { - /* - * FW expects the dummy packet to have an invalid session id - - * any session id that is different than the one set in the join - */ - tx_attr = ((~wl->session_counter) << - TX_HW_ATTR_OFST_SESSION_COUNTER) & - TX_HW_ATTR_SESSION_COUNTER; - - tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; - } else { - /* configure the tx attributes */ - tx_attr = - wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; - } + /* queue (we use same identifiers for tid's and ac's */ + ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); + desc->tid = ac; if (wl->bss_type != BSS_TYPE_AP_BSS) { desc->aid = hlid; @@ -303,37 +237,20 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; desc->reserved = 0; - aligned_len = wl12xx_calc_packet_alignment(wl, skb->len); - - if (wl->chip.id == CHIP_ID_1283_PG20) { - desc->wl128x_mem.extra_bytes = aligned_len - skb->len; - desc->length = cpu_to_le16(aligned_len >> 2); - - wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " - "tx_attr: 0x%x len: %d life: %d mem: %d", - desc->hlid, tx_attr, - le16_to_cpu(desc->length), - le16_to_cpu(desc->life_time), - desc->wl128x_mem.total_mem_blocks); - } else { - int pad; - - /* Store the aligned length in terms of words */ - desc->length = cpu_to_le16(aligned_len >> 2); + /* align the length (and store in terms of words) */ + pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO); + desc->length = cpu_to_le16(pad >> 2); - /* calculate number of padding bytes */ - pad = aligned_len - skb->len; - tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; - - wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " - "tx_attr: 0x%x len: %d life: %d mem: %d", pad, - desc->hlid, tx_attr, - le16_to_cpu(desc->length), - le16_to_cpu(desc->life_time), - desc->wl127x_mem.total_mem_blocks); - } + /* calculate number of padding bytes */ + pad = pad - skb->len; + tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; desc->tx_attr = cpu_to_le16(tx_attr); + + wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " + "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid, + le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length), + le16_to_cpu(desc->life_time), desc->total_mem_blocks); } /* caller must hold wl->mutex */ @@ -383,29 +300,19 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_regulate_link(wl, hlid); - } else { - wl1271_tx_update_filters(wl, skb); } wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); /* - * The length of each packet is stored in terms of - * words. Thus, we must pad the skb data to make sure its - * length is aligned. The number of padding bytes is computed - * and set in wl1271_tx_fill_hdr. - * In special cases, we want to align to a specific block size - * (eg. for wl128x with SDIO we align to 256). + * The length of each packet is stored in terms of words. Thus, we must + * pad the skb data to make sure its length is aligned. + * The number of padding bytes is computed and set in wl1271_tx_fill_hdr */ - total_len = wl12xx_calc_packet_alignment(wl, skb->len); - + total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); - /* Revert side effects in the dummy packet skb, so it can be reused */ - if (wl12xx_is_dummy_packet(wl, skb)) - skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); - return total_len; } @@ -518,23 +425,10 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) { - unsigned long flags; - struct sk_buff *skb = NULL; - if (wl->bss_type == BSS_TYPE_AP_BSS) - skb = wl1271_ap_skb_dequeue(wl); - else - skb = wl1271_sta_skb_dequeue(wl); - - if (!skb && - test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { - skb = wl->dummy_packet; - spin_lock_irqsave(&wl->wl_lock, flags); - wl->tx_queue_count--; - spin_unlock_irqrestore(&wl->wl_lock, flags); - } + return wl1271_ap_skb_dequeue(wl); - return skb; + return wl1271_sta_skb_dequeue(wl); } static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) @@ -542,9 +436,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) unsigned long flags; int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - if (wl12xx_is_dummy_packet(wl, skb)) { - set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); - } else if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (wl->bss_type == BSS_TYPE_AP_BSS) { u8 hlid = wl1271_tx_get_hlid(skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); @@ -562,14 +454,22 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) void wl1271_tx_work_locked(struct wl1271 *wl) { struct sk_buff *skb; + bool woken_up = false; u32 buf_offset = 0; bool sent_packets = false; int ret; if (unlikely(wl->state == WL1271_STATE_OFF)) - return; + goto out; while ((skb = wl1271_skb_dequeue(wl))) { + if (!woken_up) { + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_ack; + woken_up = true; + } + ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); if (ret == -EAGAIN) { /* @@ -616,22 +516,18 @@ void wl1271_tx_work_locked(struct wl1271 *wl) wl1271_handle_tx_low_watermark(wl); } + +out: + if (woken_up) + wl1271_ps_elp_sleep(wl); } void wl1271_tx_work(struct work_struct *work) { struct wl1271 *wl = container_of(work, struct wl1271, tx_work); - int ret; mutex_lock(&wl->mutex); - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - wl1271_tx_work_locked(wl); - - wl1271_ps_elp_wakeup(wl); -out: mutex_unlock(&wl->mutex); } @@ -653,11 +549,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, skb = wl->tx_frames[id]; info = IEEE80211_SKB_CB(skb); - if (wl12xx_is_dummy_packet(wl, skb)) { - wl1271_free_tx_id(wl, id); - return; - } - /* update the TX status info */ if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) @@ -787,13 +678,10 @@ void wl1271_tx_reset(struct wl1271 *wl) while ((skb = skb_dequeue(&wl->tx_queue[i]))) { wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - - if (!wl12xx_is_dummy_packet(wl, skb)) { - info = IEEE80211_SKB_CB(skb); - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; - ieee80211_tx_status(wl->hw, skb); - } + info = IEEE80211_SKB_CB(skb); + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; + ieee80211_tx_status(wl->hw, skb); } } } @@ -814,27 +702,21 @@ void wl1271_tx_reset(struct wl1271 *wl) wl1271_free_tx_id(wl, i); wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - if (!wl12xx_is_dummy_packet(wl, skb)) { - /* - * Remove private headers before passing the skb to - * mac80211 - */ - info = IEEE80211_SKB_CB(skb); - skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); - if (info->control.hw_key && - info->control.hw_key->cipher == - WLAN_CIPHER_SUITE_TKIP) { - int hdrlen = ieee80211_get_hdrlen_from_skb(skb); - memmove(skb->data + WL1271_TKIP_IV_SPACE, - skb->data, hdrlen); - skb_pull(skb, WL1271_TKIP_IV_SPACE); - } + /* Remove private headers before passing the skb to mac80211 */ + info = IEEE80211_SKB_CB(skb); + skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); + if (info->control.hw_key && + info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { + int hdrlen = ieee80211_get_hdrlen_from_skb(skb); + memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, + hdrlen); + skb_pull(skb, WL1271_TKIP_IV_SPACE); + } - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; - ieee80211_tx_status(wl->hw, skb); - } + ieee80211_tx_status(wl->hw, skb); } } diff --git a/trunk/drivers/net/wireless/wl12xx/tx.h b/trunk/drivers/net/wireless/wl12xx/tx.h index fc7835c4cf63..02f07fa66e82 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.h +++ b/trunk/drivers/net/wireless/wl12xx/tx.h @@ -25,6 +25,7 @@ #ifndef __TX_H__ #define __TX_H__ +#define TX_HW_BLOCK_SPARE 2 #define TX_HW_BLOCK_SIZE 252 #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 @@ -40,7 +41,6 @@ BIT(8) | BIT(9)) #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) -#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 #define TX_HW_ATTR_OFST_HEADER_PAD 1 @@ -55,60 +55,20 @@ #define WL1271_TX_ALIGN_TO 4 #define WL1271_TKIP_IV_SPACE 4 -/* Used for management frames and dummy packets */ -#define WL1271_TID_MGMT 7 - -struct wl127x_tx_mem { - /* - * Number of extra memory blocks to allocate for this packet - * in addition to the number of blocks derived from the packet - * length. - */ - u8 extra_blocks; - /* - * Total number of memory blocks allocated by the host for - * this packet. Must be equal or greater than the actual - * blocks number allocated by HW. - */ - u8 total_mem_blocks; -} __packed; - -struct wl128x_tx_mem { - /* - * Total number of memory blocks allocated by the host for - * this packet. - */ - u8 total_mem_blocks; - /* - * Number of extra bytes, at the end of the frame. the host - * uses this padding to complete each frame to integer number - * of SDIO blocks. - */ - u8 extra_bytes; -} __packed; - -/* - * On wl128x based devices, when TX packets are aggregated, each packet - * size must be aligned to the SDIO block size. The maximum block size - * is bounded by the type of the padded bytes field that is sent to the - * FW. Currently the type is u8, so the maximum block size is 256 bytes. - */ -#define WL12XX_BUS_BLOCK_SIZE min(512u, \ - (1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes)))) - struct wl1271_tx_hw_descr { /* Length of packet in words, including descriptor+header+data */ __le16 length; - union { - struct wl127x_tx_mem wl127x_mem; - struct wl128x_tx_mem wl128x_mem; - } __packed; + /* Number of extra memory blocks to allocate for this packet in + addition to the number of blocks derived from the packet length */ + u8 extra_mem_blocks; + /* Total number of memory blocks allocated by the host for this packet. + Must be equal or greater than the actual blocks number allocated by + HW!! */ + u8 total_mem_blocks; /* Device time (in us) when the packet arrived to the driver */ __le32 start_time; - /* - * Max delay in TUs until transmission. The last device time the - * packet can be transmitted is: start_time + (1024 * life_time) - */ + /* Max delay in TUs until transmission. The last device time the + packet can be transmitted is: startTime+(1024*LifeTime) */ __le16 life_time; /* Bitwise fields - see TX_ATTR... definitions above. */ __le16 tx_attr; diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/wl12xx/wl12xx.h index 7c521af58e7d..86be83e25ec5 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx.h @@ -131,16 +131,9 @@ extern u32 wl12xx_debug_level; #define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" -#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" -#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" -#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin" +#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" -/* - * wl127x and wl128x are using the same NVS file name. However, the - * ini parameters between them are different. The driver validates - * the correct NVS size in wl1271_boot_upload_nvs(). - */ -#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin" +#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin" #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) @@ -172,6 +165,7 @@ extern u32 wl12xx_debug_level; #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) #define WL1271_AP_BSS_INDEX 0 +#define WL1271_AP_DEF_INACTIV_SEC 300 #define WL1271_AP_DEF_BEACON_EXP 20 #define ACX_TX_DESCRIPTORS 32 @@ -206,29 +200,13 @@ struct wl1271_partition_set { struct wl1271; -enum { - FW_VER_CHIP, - FW_VER_IF_TYPE, - FW_VER_MAJOR, - FW_VER_SUBTYPE, - FW_VER_MINOR, - - NUM_FW_VER -}; - -#define FW_VER_CHIP_WL127X 6 -#define FW_VER_CHIP_WL128X 7 - -#define FW_VER_IF_TYPE_STA 1 -#define FW_VER_IF_TYPE_AP 2 - -#define FW_VER_MINOR_1_SPARE_STA_MIN 58 -#define FW_VER_MINOR_1_SPARE_AP_MIN 47 +#define WL12XX_NUM_FW_VER 5 +/* FIXME: I'm not sure about this structure name */ struct wl1271_chip { u32 id; char fw_ver_str[ETHTOOL_BUSINFO_LEN]; - unsigned int fw_ver[NUM_FW_VER]; + unsigned int fw_ver[WL12XX_NUM_FW_VER]; }; struct wl1271_stats { @@ -283,8 +261,6 @@ struct wl1271_fw_sta_status { u8 tx_total; u8 reserved1; __le16 reserved2; - /* Total structure size is 68 bytes */ - u32 padding; } __packed; struct wl1271_fw_full_status { @@ -301,10 +277,9 @@ struct wl1271_rx_mem_pool_addr { u32 addr_extra; }; -#define WL1271_MAX_CHANNELS 64 struct wl1271_scan { struct cfg80211_scan_request *req; - unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)]; + bool *scanned_ch; bool failed; u8 state; u8 ssid[IW_ESSID_MAX_SIZE+1]; @@ -322,7 +297,6 @@ struct wl1271_if_operations { struct device* (*dev)(struct wl1271 *wl); void (*enable_irq)(struct wl1271 *wl); void (*disable_irq)(struct wl1271 *wl); - void (*set_block_size) (struct wl1271 *wl, unsigned int blksz); }; #define MAX_NUM_KEYS 14 @@ -353,9 +327,7 @@ enum wl12xx_flags { WL1271_FLAG_PSPOLL_FAILURE, WL1271_FLAG_STA_STATE_SENT, WL1271_FLAG_FW_TX_BUSY, - WL1271_FLAG_AP_STARTED, - WL1271_FLAG_IF_INITIALIZED, - WL1271_FLAG_DUMMY_PACKET_PENDING, + WL1271_FLAG_AP_STARTED }; struct wl1271_link { @@ -399,7 +371,7 @@ struct wl1271 { u8 *fw; size_t fw_len; u8 fw_bss_type; - void *nvs; + struct wl1271_nvs_file *nvs; size_t nvs_len; s8 hw_pg_ver; @@ -417,7 +389,6 @@ struct wl1271 { /* Accounting for allocated / available TX blocks on HW */ u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_available; - u32 tx_allocated_blocks; u32 tx_results_count; /* Transmitted TX packets counter for chipset interface */ @@ -459,9 +430,6 @@ struct wl1271 { /* Intermediate buffer, used for packet aggregation */ u8 *aggr_buf; - /* Reusable dummy packet template */ - struct sk_buff *dummy_packet; - /* Network stack work */ struct work_struct netstack_work; @@ -559,8 +527,6 @@ struct wl1271 { bool ba_support; u8 ba_rx_bitmap; - int tcxo_clock; - /* * AP-mode - links indexed by HLID. The global and broadcast links * are always active. @@ -578,9 +544,6 @@ struct wl1271 { /* Quirks of specific hardware revisions */ unsigned int quirks; - - /* Platform limitations */ - unsigned int platform_quirks; }; struct wl1271_station { @@ -613,15 +576,6 @@ int wl1271_plt_stop(struct wl1271 *wl); /* Quirks */ /* Each RX/TX transaction requires an end-of-transaction transfer */ -#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) - -/* - * Older firmwares use 2 spare TX blocks - * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47) - */ -#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) - -/* WL128X requires aggregated packets to be aligned to the SDIO block size */ -#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) +#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) #endif diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index ff306d763e37..a73a305d3cba 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -557,7 +557,7 @@ int zd_chip_unlock_phy_regs(struct zd_chip *chip) return r; } -/* ZD_CR157 can be optionally patched by the EEPROM for original ZD1211 */ +/* CR157 can be optionally patched by the EEPROM for original ZD1211 */ static int patch_cr157(struct zd_chip *chip) { int r; @@ -571,7 +571,7 @@ static int patch_cr157(struct zd_chip *chip) return r; dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); - return zd_iowrite32_locked(chip, value >> 8, ZD_CR157); + return zd_iowrite32_locked(chip, value >> 8, CR157); } /* @@ -593,8 +593,8 @@ static int patch_6m_band_edge(struct zd_chip *chip, u8 channel) int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel) { struct zd_ioreq16 ioreqs[] = { - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, - { ZD_CR47, 0x1e }, + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR47, 0x1e }, }; /* FIXME: Channel 11 is not the edge for all regulatory domains. */ @@ -608,69 +608,69 @@ int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel) static int zd1211_hw_reset_phy(struct zd_chip *chip) { static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR0, 0x0a }, { ZD_CR1, 0x06 }, { ZD_CR2, 0x26 }, - { ZD_CR3, 0x38 }, { ZD_CR4, 0x80 }, { ZD_CR9, 0xa0 }, - { ZD_CR10, 0x81 }, { ZD_CR11, 0x00 }, { ZD_CR12, 0x7f }, - { ZD_CR13, 0x8c }, { ZD_CR14, 0x80 }, { ZD_CR15, 0x3d }, - { ZD_CR16, 0x20 }, { ZD_CR17, 0x1e }, { ZD_CR18, 0x0a }, - { ZD_CR19, 0x48 }, { ZD_CR20, 0x0c }, { ZD_CR21, 0x0c }, - { ZD_CR22, 0x23 }, { ZD_CR23, 0x90 }, { ZD_CR24, 0x14 }, - { ZD_CR25, 0x40 }, { ZD_CR26, 0x10 }, { ZD_CR27, 0x19 }, - { ZD_CR28, 0x7f }, { ZD_CR29, 0x80 }, { ZD_CR30, 0x4b }, - { ZD_CR31, 0x60 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x08 }, - { ZD_CR34, 0x06 }, { ZD_CR35, 0x0a }, { ZD_CR36, 0x00 }, - { ZD_CR37, 0x00 }, { ZD_CR38, 0x38 }, { ZD_CR39, 0x0c }, - { ZD_CR40, 0x84 }, { ZD_CR41, 0x2a }, { ZD_CR42, 0x80 }, - { ZD_CR43, 0x10 }, { ZD_CR44, 0x12 }, { ZD_CR46, 0xff }, - { ZD_CR47, 0x1E }, { ZD_CR48, 0x26 }, { ZD_CR49, 0x5b }, - { ZD_CR64, 0xd0 }, { ZD_CR65, 0x04 }, { ZD_CR66, 0x58 }, - { ZD_CR67, 0xc9 }, { ZD_CR68, 0x88 }, { ZD_CR69, 0x41 }, - { ZD_CR70, 0x23 }, { ZD_CR71, 0x10 }, { ZD_CR72, 0xff }, - { ZD_CR73, 0x32 }, { ZD_CR74, 0x30 }, { ZD_CR75, 0x65 }, - { ZD_CR76, 0x41 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x30 }, - { ZD_CR79, 0x68 }, { ZD_CR80, 0x64 }, { ZD_CR81, 0x64 }, - { ZD_CR82, 0x00 }, { ZD_CR83, 0x00 }, { ZD_CR84, 0x00 }, - { ZD_CR85, 0x02 }, { ZD_CR86, 0x00 }, { ZD_CR87, 0x00 }, - { ZD_CR88, 0xff }, { ZD_CR89, 0xfc }, { ZD_CR90, 0x00 }, - { ZD_CR91, 0x00 }, { ZD_CR92, 0x00 }, { ZD_CR93, 0x08 }, - { ZD_CR94, 0x00 }, { ZD_CR95, 0x00 }, { ZD_CR96, 0xff }, - { ZD_CR97, 0xe7 }, { ZD_CR98, 0x00 }, { ZD_CR99, 0x00 }, - { ZD_CR100, 0x00 }, { ZD_CR101, 0xae }, { ZD_CR102, 0x02 }, - { ZD_CR103, 0x00 }, { ZD_CR104, 0x03 }, { ZD_CR105, 0x65 }, - { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, { ZD_CR108, 0x0a }, - { ZD_CR109, 0xaa }, { ZD_CR110, 0xaa }, { ZD_CR111, 0x25 }, - { ZD_CR112, 0x25 }, { ZD_CR113, 0x00 }, { ZD_CR119, 0x1e }, - { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 }, + { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, + { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, + { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, + { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, + { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, + { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, + { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, + { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, + { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, + { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, + { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, + { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, + { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, + { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, + { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, + { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, + { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, + { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, + { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, + { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, + { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, + { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, + { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, + { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, + { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, + { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, + { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, + { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, + { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, + { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, + { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, + { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, + { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, { }, - { ZD_CR5, 0x00 }, { ZD_CR6, 0x00 }, { ZD_CR7, 0x00 }, - { ZD_CR8, 0x00 }, { ZD_CR9, 0x20 }, { ZD_CR12, 0xf0 }, - { ZD_CR20, 0x0e }, { ZD_CR21, 0x0e }, { ZD_CR27, 0x10 }, - { ZD_CR44, 0x33 }, { ZD_CR47, 0x1E }, { ZD_CR83, 0x24 }, - { ZD_CR84, 0x04 }, { ZD_CR85, 0x00 }, { ZD_CR86, 0x0C }, - { ZD_CR87, 0x12 }, { ZD_CR88, 0x0C }, { ZD_CR89, 0x00 }, - { ZD_CR90, 0x10 }, { ZD_CR91, 0x08 }, { ZD_CR93, 0x00 }, - { ZD_CR94, 0x01 }, { ZD_CR95, 0x00 }, { ZD_CR96, 0x50 }, - { ZD_CR97, 0x37 }, { ZD_CR98, 0x35 }, { ZD_CR101, 0x13 }, - { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 }, - { ZD_CR105, 0x12 }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 }, - { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 }, - { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 }, - { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR120, 0x4f }, - { ZD_CR125, 0xaa }, { ZD_CR127, 0x03 }, { ZD_CR128, 0x14 }, - { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, { ZD_CR131, 0x0C }, - { ZD_CR136, 0xdf }, { ZD_CR137, 0x40 }, { ZD_CR138, 0xa0 }, - { ZD_CR139, 0xb0 }, { ZD_CR140, 0x99 }, { ZD_CR141, 0x82 }, - { ZD_CR142, 0x54 }, { ZD_CR143, 0x1c }, { ZD_CR144, 0x6c }, - { ZD_CR147, 0x07 }, { ZD_CR148, 0x4c }, { ZD_CR149, 0x50 }, - { ZD_CR150, 0x0e }, { ZD_CR151, 0x18 }, { ZD_CR160, 0xfe }, - { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa }, - { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe }, - { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba }, - { ZD_CR170, 0xba }, { ZD_CR171, 0xba }, - /* Note: ZD_CR204 must lead the ZD_CR203 */ - { ZD_CR204, 0x7d }, + { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, + { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, + { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, + { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, + { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, + { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, + { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, + { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, + { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, + { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, + { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, + { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, + { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, + { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, + { CR125, 0xaa }, { CR127, 0x03 }, { CR128, 0x14 }, + { CR129, 0x12 }, { CR130, 0x10 }, { CR131, 0x0C }, + { CR136, 0xdf }, { CR137, 0x40 }, { CR138, 0xa0 }, + { CR139, 0xb0 }, { CR140, 0x99 }, { CR141, 0x82 }, + { CR142, 0x54 }, { CR143, 0x1c }, { CR144, 0x6c }, + { CR147, 0x07 }, { CR148, 0x4c }, { CR149, 0x50 }, + { CR150, 0x0e }, { CR151, 0x18 }, { CR160, 0xfe }, + { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, + { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, + { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, + { CR170, 0xba }, { CR171, 0xba }, + /* Note: CR204 must lead the CR203 */ + { CR204, 0x7d }, { }, - { ZD_CR203, 0x30 }, + { CR203, 0x30 }, }; int r, t; @@ -697,62 +697,62 @@ static int zd1211_hw_reset_phy(struct zd_chip *chip) static int zd1211b_hw_reset_phy(struct zd_chip *chip) { static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR0, 0x14 }, { ZD_CR1, 0x06 }, { ZD_CR2, 0x26 }, - { ZD_CR3, 0x38 }, { ZD_CR4, 0x80 }, { ZD_CR9, 0xe0 }, - { ZD_CR10, 0x81 }, - /* power control { { ZD_CR11, 1 << 6 }, */ - { ZD_CR11, 0x00 }, - { ZD_CR12, 0xf0 }, { ZD_CR13, 0x8c }, { ZD_CR14, 0x80 }, - { ZD_CR15, 0x3d }, { ZD_CR16, 0x20 }, { ZD_CR17, 0x1e }, - { ZD_CR18, 0x0a }, { ZD_CR19, 0x48 }, - { ZD_CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ - { ZD_CR21, 0x0e }, { ZD_CR22, 0x23 }, { ZD_CR23, 0x90 }, - { ZD_CR24, 0x14 }, { ZD_CR25, 0x40 }, { ZD_CR26, 0x10 }, - { ZD_CR27, 0x10 }, { ZD_CR28, 0x7f }, { ZD_CR29, 0x80 }, - { ZD_CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ - { ZD_CR31, 0x60 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x08 }, - { ZD_CR34, 0x06 }, { ZD_CR35, 0x0a }, { ZD_CR36, 0x00 }, - { ZD_CR37, 0x00 }, { ZD_CR38, 0x38 }, { ZD_CR39, 0x0c }, - { ZD_CR40, 0x84 }, { ZD_CR41, 0x2a }, { ZD_CR42, 0x80 }, - { ZD_CR43, 0x10 }, { ZD_CR44, 0x33 }, { ZD_CR46, 0xff }, - { ZD_CR47, 0x1E }, { ZD_CR48, 0x26 }, { ZD_CR49, 0x5b }, - { ZD_CR64, 0xd0 }, { ZD_CR65, 0x04 }, { ZD_CR66, 0x58 }, - { ZD_CR67, 0xc9 }, { ZD_CR68, 0x88 }, { ZD_CR69, 0x41 }, - { ZD_CR70, 0x23 }, { ZD_CR71, 0x10 }, { ZD_CR72, 0xff }, - { ZD_CR73, 0x32 }, { ZD_CR74, 0x30 }, { ZD_CR75, 0x65 }, - { ZD_CR76, 0x41 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x30 }, - { ZD_CR79, 0xf0 }, { ZD_CR80, 0x64 }, { ZD_CR81, 0x64 }, - { ZD_CR82, 0x00 }, { ZD_CR83, 0x24 }, { ZD_CR84, 0x04 }, - { ZD_CR85, 0x00 }, { ZD_CR86, 0x0c }, { ZD_CR87, 0x12 }, - { ZD_CR88, 0x0c }, { ZD_CR89, 0x00 }, { ZD_CR90, 0x58 }, - { ZD_CR91, 0x04 }, { ZD_CR92, 0x00 }, { ZD_CR93, 0x00 }, - { ZD_CR94, 0x01 }, - { ZD_CR95, 0x20 }, /* ZD1211B */ - { ZD_CR96, 0x50 }, { ZD_CR97, 0x37 }, { ZD_CR98, 0x35 }, - { ZD_CR99, 0x00 }, { ZD_CR100, 0x01 }, { ZD_CR101, 0x13 }, - { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 }, - { ZD_CR105, 0x12 }, { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, - { ZD_CR108, 0x0a }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 }, - { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 }, - { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 }, - { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x1e }, - { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 }, - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, - { ZD_CR131, 0x0c }, { ZD_CR136, 0xdf }, { ZD_CR137, 0xa0 }, - { ZD_CR138, 0xa8 }, { ZD_CR139, 0xb4 }, { ZD_CR140, 0x98 }, - { ZD_CR141, 0x82 }, { ZD_CR142, 0x53 }, { ZD_CR143, 0x1c }, - { ZD_CR144, 0x6c }, { ZD_CR147, 0x07 }, { ZD_CR148, 0x40 }, - { ZD_CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ - { ZD_CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ - { ZD_CR151, 0x18 }, { ZD_CR159, 0x70 }, { ZD_CR160, 0xfe }, - { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa }, - { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe }, - { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba }, - { ZD_CR170, 0xba }, { ZD_CR171, 0xba }, - /* Note: ZD_CR204 must lead the ZD_CR203 */ - { ZD_CR204, 0x7d }, + { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, + { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, + { CR10, 0x81 }, + /* power control { { CR11, 1 << 6 }, */ + { CR11, 0x00 }, + { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, + { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, + { CR18, 0x0a }, { CR19, 0x48 }, + { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ + { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, + { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, + { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, + { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ + { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, + { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, + { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, + { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, + { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, + { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, + { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, + { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, + { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, + { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, + { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, + { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, + { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, + { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, + { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, + { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, + { CR94, 0x01 }, + { CR95, 0x20 }, /* ZD1211B */ + { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, + { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, + { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, + { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, + { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, + { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, + { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, + { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, + { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, + { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, + { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, + { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, + { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ + { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ + { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, + { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, + { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, + { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, + { CR170, 0xba }, { CR171, 0xba }, + /* Note: CR204 must lead the CR203 */ + { CR204, 0x7d }, {}, - { ZD_CR203, 0x30 }, + { CR203, 0x30 }, }; int r, t; @@ -1200,24 +1200,24 @@ int zd_chip_init_hw(struct zd_chip *chip) static int update_pwr_int(struct zd_chip *chip, u8 channel) { u8 value = chip->pwr_int_values[channel - 1]; - return zd_iowrite16_locked(chip, value, ZD_CR31); + return zd_iowrite16_locked(chip, value, CR31); } static int update_pwr_cal(struct zd_chip *chip, u8 channel) { u8 value = chip->pwr_cal_values[channel-1]; - return zd_iowrite16_locked(chip, value, ZD_CR68); + return zd_iowrite16_locked(chip, value, CR68); } static int update_ofdm_cal(struct zd_chip *chip, u8 channel) { struct zd_ioreq16 ioreqs[3]; - ioreqs[0].addr = ZD_CR67; + ioreqs[0].addr = CR67; ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; - ioreqs[1].addr = ZD_CR66; + ioreqs[1].addr = CR66; ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; - ioreqs[2].addr = ZD_CR65; + ioreqs[2].addr = CR65; ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -1236,9 +1236,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip, return r; if (zd_chip_is_zd1211b(chip)) { static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR69, 0x28 }, + { CR69, 0x28 }, {}, - { ZD_CR69, 0x2a }, + { CR69, 0x2a }, }; r = update_ofdm_cal(chip, channel); @@ -1269,7 +1269,7 @@ static int patch_cck_gain(struct zd_chip *chip) if (r) return r; dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); - return zd_iowrite16_locked(chip, value & 0xff, ZD_CR47); + return zd_iowrite16_locked(chip, value & 0xff, CR47); } int zd_chip_set_channel(struct zd_chip *chip, u8 channel) @@ -1505,9 +1505,9 @@ int zd_rfwritev_locked(struct zd_chip *chip, int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) { const struct zd_ioreq16 ioreqs[] = { - { ZD_CR244, (value >> 16) & 0xff }, - { ZD_CR243, (value >> 8) & 0xff }, - { ZD_CR242, value & 0xff }, + { CR244, (value >> 16) & 0xff }, + { CR243, (value >> 8) & 0xff }, + { CR242, value & 0xff }, }; ZD_ASSERT(mutex_is_locked(&chip->mutex)); return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h index 4be7c3b5b265..14e4402a6111 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h @@ -61,288 +61,277 @@ enum { #define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset))) /* 8-bit hardware registers */ -#define ZD_CR0 CTL_REG(0x0000) -#define ZD_CR1 CTL_REG(0x0004) -#define ZD_CR2 CTL_REG(0x0008) -#define ZD_CR3 CTL_REG(0x000C) +#define CR0 CTL_REG(0x0000) +#define CR1 CTL_REG(0x0004) +#define CR2 CTL_REG(0x0008) +#define CR3 CTL_REG(0x000C) -#define ZD_CR5 CTL_REG(0x0010) +#define CR5 CTL_REG(0x0010) /* bit 5: if set short preamble used * bit 6: filter band - Japan channel 14 on, else off */ -#define ZD_CR6 CTL_REG(0x0014) -#define ZD_CR7 CTL_REG(0x0018) -#define ZD_CR8 CTL_REG(0x001C) +#define CR6 CTL_REG(0x0014) +#define CR7 CTL_REG(0x0018) +#define CR8 CTL_REG(0x001C) -#define ZD_CR4 CTL_REG(0x0020) +#define CR4 CTL_REG(0x0020) -#define ZD_CR9 CTL_REG(0x0024) -/* bit 2: antenna switch (together with ZD_CR10) */ -#define ZD_CR10 CTL_REG(0x0028) -/* bit 1: antenna switch (together with ZD_CR9) - * RF2959 controls with ZD_CR11 radion on and off +#define CR9 CTL_REG(0x0024) +/* bit 2: antenna switch (together with CR10) */ +#define CR10 CTL_REG(0x0028) +/* bit 1: antenna switch (together with CR9) + * RF2959 controls with CR11 radion on and off */ -#define ZD_CR11 CTL_REG(0x002C) +#define CR11 CTL_REG(0x002C) /* bit 6: TX power control for OFDM - * RF2959 controls with ZD_CR10 radio on and off + * RF2959 controls with CR10 radio on and off */ -#define ZD_CR12 CTL_REG(0x0030) -#define ZD_CR13 CTL_REG(0x0034) -#define ZD_CR14 CTL_REG(0x0038) -#define ZD_CR15 CTL_REG(0x003C) -#define ZD_CR16 CTL_REG(0x0040) -#define ZD_CR17 CTL_REG(0x0044) -#define ZD_CR18 CTL_REG(0x0048) -#define ZD_CR19 CTL_REG(0x004C) -#define ZD_CR20 CTL_REG(0x0050) -#define ZD_CR21 CTL_REG(0x0054) -#define ZD_CR22 CTL_REG(0x0058) -#define ZD_CR23 CTL_REG(0x005C) -#define ZD_CR24 CTL_REG(0x0060) /* CCA threshold */ -#define ZD_CR25 CTL_REG(0x0064) -#define ZD_CR26 CTL_REG(0x0068) -#define ZD_CR27 CTL_REG(0x006C) -#define ZD_CR28 CTL_REG(0x0070) -#define ZD_CR29 CTL_REG(0x0074) -#define ZD_CR30 CTL_REG(0x0078) -#define ZD_CR31 CTL_REG(0x007C) /* TX power control for RF in - * CCK mode - */ -#define ZD_CR32 CTL_REG(0x0080) -#define ZD_CR33 CTL_REG(0x0084) -#define ZD_CR34 CTL_REG(0x0088) -#define ZD_CR35 CTL_REG(0x008C) -#define ZD_CR36 CTL_REG(0x0090) -#define ZD_CR37 CTL_REG(0x0094) -#define ZD_CR38 CTL_REG(0x0098) -#define ZD_CR39 CTL_REG(0x009C) -#define ZD_CR40 CTL_REG(0x00A0) -#define ZD_CR41 CTL_REG(0x00A4) -#define ZD_CR42 CTL_REG(0x00A8) -#define ZD_CR43 CTL_REG(0x00AC) -#define ZD_CR44 CTL_REG(0x00B0) -#define ZD_CR45 CTL_REG(0x00B4) -#define ZD_CR46 CTL_REG(0x00B8) -#define ZD_CR47 CTL_REG(0x00BC) /* CCK baseband gain - * (patch value might be in EEPROM) - */ -#define ZD_CR48 CTL_REG(0x00C0) -#define ZD_CR49 CTL_REG(0x00C4) -#define ZD_CR50 CTL_REG(0x00C8) -#define ZD_CR51 CTL_REG(0x00CC) /* TX power control for RF in - * 6-36M modes - */ -#define ZD_CR52 CTL_REG(0x00D0) /* TX power control for RF in - * 48M mode - */ -#define ZD_CR53 CTL_REG(0x00D4) /* TX power control for RF in - * 54M mode - */ -#define ZD_CR54 CTL_REG(0x00D8) -#define ZD_CR55 CTL_REG(0x00DC) -#define ZD_CR56 CTL_REG(0x00E0) -#define ZD_CR57 CTL_REG(0x00E4) -#define ZD_CR58 CTL_REG(0x00E8) -#define ZD_CR59 CTL_REG(0x00EC) -#define ZD_CR60 CTL_REG(0x00F0) -#define ZD_CR61 CTL_REG(0x00F4) -#define ZD_CR62 CTL_REG(0x00F8) -#define ZD_CR63 CTL_REG(0x00FC) -#define ZD_CR64 CTL_REG(0x0100) -#define ZD_CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ -#define ZD_CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ -#define ZD_CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ -#define ZD_CR68 CTL_REG(0x0110) /* CCK calibration */ -#define ZD_CR69 CTL_REG(0x0114) -#define ZD_CR70 CTL_REG(0x0118) -#define ZD_CR71 CTL_REG(0x011C) -#define ZD_CR72 CTL_REG(0x0120) -#define ZD_CR73 CTL_REG(0x0124) -#define ZD_CR74 CTL_REG(0x0128) -#define ZD_CR75 CTL_REG(0x012C) -#define ZD_CR76 CTL_REG(0x0130) -#define ZD_CR77 CTL_REG(0x0134) -#define ZD_CR78 CTL_REG(0x0138) -#define ZD_CR79 CTL_REG(0x013C) -#define ZD_CR80 CTL_REG(0x0140) -#define ZD_CR81 CTL_REG(0x0144) -#define ZD_CR82 CTL_REG(0x0148) -#define ZD_CR83 CTL_REG(0x014C) -#define ZD_CR84 CTL_REG(0x0150) -#define ZD_CR85 CTL_REG(0x0154) -#define ZD_CR86 CTL_REG(0x0158) -#define ZD_CR87 CTL_REG(0x015C) -#define ZD_CR88 CTL_REG(0x0160) -#define ZD_CR89 CTL_REG(0x0164) -#define ZD_CR90 CTL_REG(0x0168) -#define ZD_CR91 CTL_REG(0x016C) -#define ZD_CR92 CTL_REG(0x0170) -#define ZD_CR93 CTL_REG(0x0174) -#define ZD_CR94 CTL_REG(0x0178) -#define ZD_CR95 CTL_REG(0x017C) -#define ZD_CR96 CTL_REG(0x0180) -#define ZD_CR97 CTL_REG(0x0184) -#define ZD_CR98 CTL_REG(0x0188) -#define ZD_CR99 CTL_REG(0x018C) -#define ZD_CR100 CTL_REG(0x0190) -#define ZD_CR101 CTL_REG(0x0194) -#define ZD_CR102 CTL_REG(0x0198) -#define ZD_CR103 CTL_REG(0x019C) -#define ZD_CR104 CTL_REG(0x01A0) -#define ZD_CR105 CTL_REG(0x01A4) -#define ZD_CR106 CTL_REG(0x01A8) -#define ZD_CR107 CTL_REG(0x01AC) -#define ZD_CR108 CTL_REG(0x01B0) -#define ZD_CR109 CTL_REG(0x01B4) -#define ZD_CR110 CTL_REG(0x01B8) -#define ZD_CR111 CTL_REG(0x01BC) -#define ZD_CR112 CTL_REG(0x01C0) -#define ZD_CR113 CTL_REG(0x01C4) -#define ZD_CR114 CTL_REG(0x01C8) -#define ZD_CR115 CTL_REG(0x01CC) -#define ZD_CR116 CTL_REG(0x01D0) -#define ZD_CR117 CTL_REG(0x01D4) -#define ZD_CR118 CTL_REG(0x01D8) -#define ZD_CR119 CTL_REG(0x01DC) -#define ZD_CR120 CTL_REG(0x01E0) -#define ZD_CR121 CTL_REG(0x01E4) -#define ZD_CR122 CTL_REG(0x01E8) -#define ZD_CR123 CTL_REG(0x01EC) -#define ZD_CR124 CTL_REG(0x01F0) -#define ZD_CR125 CTL_REG(0x01F4) -#define ZD_CR126 CTL_REG(0x01F8) -#define ZD_CR127 CTL_REG(0x01FC) -#define ZD_CR128 CTL_REG(0x0200) -#define ZD_CR129 CTL_REG(0x0204) -#define ZD_CR130 CTL_REG(0x0208) -#define ZD_CR131 CTL_REG(0x020C) -#define ZD_CR132 CTL_REG(0x0210) -#define ZD_CR133 CTL_REG(0x0214) -#define ZD_CR134 CTL_REG(0x0218) -#define ZD_CR135 CTL_REG(0x021C) -#define ZD_CR136 CTL_REG(0x0220) -#define ZD_CR137 CTL_REG(0x0224) -#define ZD_CR138 CTL_REG(0x0228) -#define ZD_CR139 CTL_REG(0x022C) -#define ZD_CR140 CTL_REG(0x0230) -#define ZD_CR141 CTL_REG(0x0234) -#define ZD_CR142 CTL_REG(0x0238) -#define ZD_CR143 CTL_REG(0x023C) -#define ZD_CR144 CTL_REG(0x0240) -#define ZD_CR145 CTL_REG(0x0244) -#define ZD_CR146 CTL_REG(0x0248) -#define ZD_CR147 CTL_REG(0x024C) -#define ZD_CR148 CTL_REG(0x0250) -#define ZD_CR149 CTL_REG(0x0254) -#define ZD_CR150 CTL_REG(0x0258) -#define ZD_CR151 CTL_REG(0x025C) -#define ZD_CR152 CTL_REG(0x0260) -#define ZD_CR153 CTL_REG(0x0264) -#define ZD_CR154 CTL_REG(0x0268) -#define ZD_CR155 CTL_REG(0x026C) -#define ZD_CR156 CTL_REG(0x0270) -#define ZD_CR157 CTL_REG(0x0274) -#define ZD_CR158 CTL_REG(0x0278) -#define ZD_CR159 CTL_REG(0x027C) -#define ZD_CR160 CTL_REG(0x0280) -#define ZD_CR161 CTL_REG(0x0284) -#define ZD_CR162 CTL_REG(0x0288) -#define ZD_CR163 CTL_REG(0x028C) -#define ZD_CR164 CTL_REG(0x0290) -#define ZD_CR165 CTL_REG(0x0294) -#define ZD_CR166 CTL_REG(0x0298) -#define ZD_CR167 CTL_REG(0x029C) -#define ZD_CR168 CTL_REG(0x02A0) -#define ZD_CR169 CTL_REG(0x02A4) -#define ZD_CR170 CTL_REG(0x02A8) -#define ZD_CR171 CTL_REG(0x02AC) -#define ZD_CR172 CTL_REG(0x02B0) -#define ZD_CR173 CTL_REG(0x02B4) -#define ZD_CR174 CTL_REG(0x02B8) -#define ZD_CR175 CTL_REG(0x02BC) -#define ZD_CR176 CTL_REG(0x02C0) -#define ZD_CR177 CTL_REG(0x02C4) -#define ZD_CR178 CTL_REG(0x02C8) -#define ZD_CR179 CTL_REG(0x02CC) -#define ZD_CR180 CTL_REG(0x02D0) -#define ZD_CR181 CTL_REG(0x02D4) -#define ZD_CR182 CTL_REG(0x02D8) -#define ZD_CR183 CTL_REG(0x02DC) -#define ZD_CR184 CTL_REG(0x02E0) -#define ZD_CR185 CTL_REG(0x02E4) -#define ZD_CR186 CTL_REG(0x02E8) -#define ZD_CR187 CTL_REG(0x02EC) -#define ZD_CR188 CTL_REG(0x02F0) -#define ZD_CR189 CTL_REG(0x02F4) -#define ZD_CR190 CTL_REG(0x02F8) -#define ZD_CR191 CTL_REG(0x02FC) -#define ZD_CR192 CTL_REG(0x0300) -#define ZD_CR193 CTL_REG(0x0304) -#define ZD_CR194 CTL_REG(0x0308) -#define ZD_CR195 CTL_REG(0x030C) -#define ZD_CR196 CTL_REG(0x0310) -#define ZD_CR197 CTL_REG(0x0314) -#define ZD_CR198 CTL_REG(0x0318) -#define ZD_CR199 CTL_REG(0x031C) -#define ZD_CR200 CTL_REG(0x0320) -#define ZD_CR201 CTL_REG(0x0324) -#define ZD_CR202 CTL_REG(0x0328) -#define ZD_CR203 CTL_REG(0x032C) /* I2C bus template value & flash - * control - */ -#define ZD_CR204 CTL_REG(0x0330) -#define ZD_CR205 CTL_REG(0x0334) -#define ZD_CR206 CTL_REG(0x0338) -#define ZD_CR207 CTL_REG(0x033C) -#define ZD_CR208 CTL_REG(0x0340) -#define ZD_CR209 CTL_REG(0x0344) -#define ZD_CR210 CTL_REG(0x0348) -#define ZD_CR211 CTL_REG(0x034C) -#define ZD_CR212 CTL_REG(0x0350) -#define ZD_CR213 CTL_REG(0x0354) -#define ZD_CR214 CTL_REG(0x0358) -#define ZD_CR215 CTL_REG(0x035C) -#define ZD_CR216 CTL_REG(0x0360) -#define ZD_CR217 CTL_REG(0x0364) -#define ZD_CR218 CTL_REG(0x0368) -#define ZD_CR219 CTL_REG(0x036C) -#define ZD_CR220 CTL_REG(0x0370) -#define ZD_CR221 CTL_REG(0x0374) -#define ZD_CR222 CTL_REG(0x0378) -#define ZD_CR223 CTL_REG(0x037C) -#define ZD_CR224 CTL_REG(0x0380) -#define ZD_CR225 CTL_REG(0x0384) -#define ZD_CR226 CTL_REG(0x0388) -#define ZD_CR227 CTL_REG(0x038C) -#define ZD_CR228 CTL_REG(0x0390) -#define ZD_CR229 CTL_REG(0x0394) -#define ZD_CR230 CTL_REG(0x0398) -#define ZD_CR231 CTL_REG(0x039C) -#define ZD_CR232 CTL_REG(0x03A0) -#define ZD_CR233 CTL_REG(0x03A4) -#define ZD_CR234 CTL_REG(0x03A8) -#define ZD_CR235 CTL_REG(0x03AC) -#define ZD_CR236 CTL_REG(0x03B0) - -#define ZD_CR240 CTL_REG(0x03C0) -/* bit 7: host-controlled RF register writes - * ZD_CR241-ZD_CR245: for hardware controlled writing of RF bits, not needed for - * USB +#define CR12 CTL_REG(0x0030) +#define CR13 CTL_REG(0x0034) +#define CR14 CTL_REG(0x0038) +#define CR15 CTL_REG(0x003C) +#define CR16 CTL_REG(0x0040) +#define CR17 CTL_REG(0x0044) +#define CR18 CTL_REG(0x0048) +#define CR19 CTL_REG(0x004C) +#define CR20 CTL_REG(0x0050) +#define CR21 CTL_REG(0x0054) +#define CR22 CTL_REG(0x0058) +#define CR23 CTL_REG(0x005C) +#define CR24 CTL_REG(0x0060) /* CCA threshold */ +#define CR25 CTL_REG(0x0064) +#define CR26 CTL_REG(0x0068) +#define CR27 CTL_REG(0x006C) +#define CR28 CTL_REG(0x0070) +#define CR29 CTL_REG(0x0074) +#define CR30 CTL_REG(0x0078) +#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ +#define CR32 CTL_REG(0x0080) +#define CR33 CTL_REG(0x0084) +#define CR34 CTL_REG(0x0088) +#define CR35 CTL_REG(0x008C) +#define CR36 CTL_REG(0x0090) +#define CR37 CTL_REG(0x0094) +#define CR38 CTL_REG(0x0098) +#define CR39 CTL_REG(0x009C) +#define CR40 CTL_REG(0x00A0) +#define CR41 CTL_REG(0x00A4) +#define CR42 CTL_REG(0x00A8) +#define CR43 CTL_REG(0x00AC) +#define CR44 CTL_REG(0x00B0) +#define CR45 CTL_REG(0x00B4) +#define CR46 CTL_REG(0x00B8) +#define CR47 CTL_REG(0x00BC) /* CCK baseband gain + * (patch value might be in EEPROM) + */ +#define CR48 CTL_REG(0x00C0) +#define CR49 CTL_REG(0x00C4) +#define CR50 CTL_REG(0x00C8) +#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ +#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ +#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ +#define CR54 CTL_REG(0x00D8) +#define CR55 CTL_REG(0x00DC) +#define CR56 CTL_REG(0x00E0) +#define CR57 CTL_REG(0x00E4) +#define CR58 CTL_REG(0x00E8) +#define CR59 CTL_REG(0x00EC) +#define CR60 CTL_REG(0x00F0) +#define CR61 CTL_REG(0x00F4) +#define CR62 CTL_REG(0x00F8) +#define CR63 CTL_REG(0x00FC) +#define CR64 CTL_REG(0x0100) +#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ +#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ +#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ +#define CR68 CTL_REG(0x0110) /* CCK calibration */ +#define CR69 CTL_REG(0x0114) +#define CR70 CTL_REG(0x0118) +#define CR71 CTL_REG(0x011C) +#define CR72 CTL_REG(0x0120) +#define CR73 CTL_REG(0x0124) +#define CR74 CTL_REG(0x0128) +#define CR75 CTL_REG(0x012C) +#define CR76 CTL_REG(0x0130) +#define CR77 CTL_REG(0x0134) +#define CR78 CTL_REG(0x0138) +#define CR79 CTL_REG(0x013C) +#define CR80 CTL_REG(0x0140) +#define CR81 CTL_REG(0x0144) +#define CR82 CTL_REG(0x0148) +#define CR83 CTL_REG(0x014C) +#define CR84 CTL_REG(0x0150) +#define CR85 CTL_REG(0x0154) +#define CR86 CTL_REG(0x0158) +#define CR87 CTL_REG(0x015C) +#define CR88 CTL_REG(0x0160) +#define CR89 CTL_REG(0x0164) +#define CR90 CTL_REG(0x0168) +#define CR91 CTL_REG(0x016C) +#define CR92 CTL_REG(0x0170) +#define CR93 CTL_REG(0x0174) +#define CR94 CTL_REG(0x0178) +#define CR95 CTL_REG(0x017C) +#define CR96 CTL_REG(0x0180) +#define CR97 CTL_REG(0x0184) +#define CR98 CTL_REG(0x0188) +#define CR99 CTL_REG(0x018C) +#define CR100 CTL_REG(0x0190) +#define CR101 CTL_REG(0x0194) +#define CR102 CTL_REG(0x0198) +#define CR103 CTL_REG(0x019C) +#define CR104 CTL_REG(0x01A0) +#define CR105 CTL_REG(0x01A4) +#define CR106 CTL_REG(0x01A8) +#define CR107 CTL_REG(0x01AC) +#define CR108 CTL_REG(0x01B0) +#define CR109 CTL_REG(0x01B4) +#define CR110 CTL_REG(0x01B8) +#define CR111 CTL_REG(0x01BC) +#define CR112 CTL_REG(0x01C0) +#define CR113 CTL_REG(0x01C4) +#define CR114 CTL_REG(0x01C8) +#define CR115 CTL_REG(0x01CC) +#define CR116 CTL_REG(0x01D0) +#define CR117 CTL_REG(0x01D4) +#define CR118 CTL_REG(0x01D8) +#define CR119 CTL_REG(0x01DC) +#define CR120 CTL_REG(0x01E0) +#define CR121 CTL_REG(0x01E4) +#define CR122 CTL_REG(0x01E8) +#define CR123 CTL_REG(0x01EC) +#define CR124 CTL_REG(0x01F0) +#define CR125 CTL_REG(0x01F4) +#define CR126 CTL_REG(0x01F8) +#define CR127 CTL_REG(0x01FC) +#define CR128 CTL_REG(0x0200) +#define CR129 CTL_REG(0x0204) +#define CR130 CTL_REG(0x0208) +#define CR131 CTL_REG(0x020C) +#define CR132 CTL_REG(0x0210) +#define CR133 CTL_REG(0x0214) +#define CR134 CTL_REG(0x0218) +#define CR135 CTL_REG(0x021C) +#define CR136 CTL_REG(0x0220) +#define CR137 CTL_REG(0x0224) +#define CR138 CTL_REG(0x0228) +#define CR139 CTL_REG(0x022C) +#define CR140 CTL_REG(0x0230) +#define CR141 CTL_REG(0x0234) +#define CR142 CTL_REG(0x0238) +#define CR143 CTL_REG(0x023C) +#define CR144 CTL_REG(0x0240) +#define CR145 CTL_REG(0x0244) +#define CR146 CTL_REG(0x0248) +#define CR147 CTL_REG(0x024C) +#define CR148 CTL_REG(0x0250) +#define CR149 CTL_REG(0x0254) +#define CR150 CTL_REG(0x0258) +#define CR151 CTL_REG(0x025C) +#define CR152 CTL_REG(0x0260) +#define CR153 CTL_REG(0x0264) +#define CR154 CTL_REG(0x0268) +#define CR155 CTL_REG(0x026C) +#define CR156 CTL_REG(0x0270) +#define CR157 CTL_REG(0x0274) +#define CR158 CTL_REG(0x0278) +#define CR159 CTL_REG(0x027C) +#define CR160 CTL_REG(0x0280) +#define CR161 CTL_REG(0x0284) +#define CR162 CTL_REG(0x0288) +#define CR163 CTL_REG(0x028C) +#define CR164 CTL_REG(0x0290) +#define CR165 CTL_REG(0x0294) +#define CR166 CTL_REG(0x0298) +#define CR167 CTL_REG(0x029C) +#define CR168 CTL_REG(0x02A0) +#define CR169 CTL_REG(0x02A4) +#define CR170 CTL_REG(0x02A8) +#define CR171 CTL_REG(0x02AC) +#define CR172 CTL_REG(0x02B0) +#define CR173 CTL_REG(0x02B4) +#define CR174 CTL_REG(0x02B8) +#define CR175 CTL_REG(0x02BC) +#define CR176 CTL_REG(0x02C0) +#define CR177 CTL_REG(0x02C4) +#define CR178 CTL_REG(0x02C8) +#define CR179 CTL_REG(0x02CC) +#define CR180 CTL_REG(0x02D0) +#define CR181 CTL_REG(0x02D4) +#define CR182 CTL_REG(0x02D8) +#define CR183 CTL_REG(0x02DC) +#define CR184 CTL_REG(0x02E0) +#define CR185 CTL_REG(0x02E4) +#define CR186 CTL_REG(0x02E8) +#define CR187 CTL_REG(0x02EC) +#define CR188 CTL_REG(0x02F0) +#define CR189 CTL_REG(0x02F4) +#define CR190 CTL_REG(0x02F8) +#define CR191 CTL_REG(0x02FC) +#define CR192 CTL_REG(0x0300) +#define CR193 CTL_REG(0x0304) +#define CR194 CTL_REG(0x0308) +#define CR195 CTL_REG(0x030C) +#define CR196 CTL_REG(0x0310) +#define CR197 CTL_REG(0x0314) +#define CR198 CTL_REG(0x0318) +#define CR199 CTL_REG(0x031C) +#define CR200 CTL_REG(0x0320) +#define CR201 CTL_REG(0x0324) +#define CR202 CTL_REG(0x0328) +#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ +#define CR204 CTL_REG(0x0330) +#define CR205 CTL_REG(0x0334) +#define CR206 CTL_REG(0x0338) +#define CR207 CTL_REG(0x033C) +#define CR208 CTL_REG(0x0340) +#define CR209 CTL_REG(0x0344) +#define CR210 CTL_REG(0x0348) +#define CR211 CTL_REG(0x034C) +#define CR212 CTL_REG(0x0350) +#define CR213 CTL_REG(0x0354) +#define CR214 CTL_REG(0x0358) +#define CR215 CTL_REG(0x035C) +#define CR216 CTL_REG(0x0360) +#define CR217 CTL_REG(0x0364) +#define CR218 CTL_REG(0x0368) +#define CR219 CTL_REG(0x036C) +#define CR220 CTL_REG(0x0370) +#define CR221 CTL_REG(0x0374) +#define CR222 CTL_REG(0x0378) +#define CR223 CTL_REG(0x037C) +#define CR224 CTL_REG(0x0380) +#define CR225 CTL_REG(0x0384) +#define CR226 CTL_REG(0x0388) +#define CR227 CTL_REG(0x038C) +#define CR228 CTL_REG(0x0390) +#define CR229 CTL_REG(0x0394) +#define CR230 CTL_REG(0x0398) +#define CR231 CTL_REG(0x039C) +#define CR232 CTL_REG(0x03A0) +#define CR233 CTL_REG(0x03A4) +#define CR234 CTL_REG(0x03A8) +#define CR235 CTL_REG(0x03AC) +#define CR236 CTL_REG(0x03B0) + +#define CR240 CTL_REG(0x03C0) +/* bit 7: host-controlled RF register writes + * CR241-CR245: for hardware controlled writing of RF bits, not needed for + * USB */ -#define ZD_CR241 CTL_REG(0x03C4) -#define ZD_CR242 CTL_REG(0x03C8) -#define ZD_CR243 CTL_REG(0x03CC) -#define ZD_CR244 CTL_REG(0x03D0) -#define ZD_CR245 CTL_REG(0x03D4) - -#define ZD_CR251 CTL_REG(0x03EC) /* only used for activation and - * deactivation of Airoha RFs AL2230 - * and AL7230B - */ -#define ZD_CR252 CTL_REG(0x03F0) -#define ZD_CR253 CTL_REG(0x03F4) -#define ZD_CR254 CTL_REG(0x03F8) -#define ZD_CR255 CTL_REG(0x03FC) +#define CR241 CTL_REG(0x03C4) +#define CR242 CTL_REG(0x03C8) +#define CR243 CTL_REG(0x03CC) +#define CR244 CTL_REG(0x03D0) +#define CR245 CTL_REG(0x03D4) + +#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of + * Airoha RFs AL2230 and AL7230B + */ +#define CR252 CTL_REG(0x03F0) +#define CR253 CTL_REG(0x03F4) +#define CR254 CTL_REG(0x03F8) +#define CR255 CTL_REG(0x03FC) #define CR_MAX_PHY_REG 255 diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf.h b/trunk/drivers/net/wireless/zd1211rw/zd_rf.h index 725b7c99b23d..79dc1035592d 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf.h @@ -55,7 +55,7 @@ struct zd_rf { * defaults to 1 (yes) */ u8 update_channel_int:1; - /* whether ZD_CR47 should be patched from the EEPROM, if the appropriate + /* whether CR47 should be patched from the EEPROM, if the appropriate * flag is set in the POD. The vendor driver suggests that this should * be done for all RF's, but a bug in their code prevents but their * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 12babcb633c3..74a8f7a55591 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -61,31 +61,31 @@ static const u32 zd1211b_al2230_table[][3] = { }; static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = { - { ZD_CR240, 0x57 }, { ZD_CR9, 0xe0 }, + { CR240, 0x57 }, { CR9, 0xe0 }, }; static const struct zd_ioreq16 ioreqs_init_al2230s[] = { - { ZD_CR47, 0x1e }, /* MARK_002 */ - { ZD_CR106, 0x22 }, - { ZD_CR107, 0x2a }, /* MARK_002 */ - { ZD_CR109, 0x13 }, /* MARK_002 */ - { ZD_CR118, 0xf8 }, /* MARK_002 */ - { ZD_CR119, 0x12 }, { ZD_CR122, 0xe0 }, - { ZD_CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ - { ZD_CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ - { ZD_CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ + { CR47, 0x1e }, /* MARK_002 */ + { CR106, 0x22 }, + { CR107, 0x2a }, /* MARK_002 */ + { CR109, 0x13 }, /* MARK_002 */ + { CR118, 0xf8 }, /* MARK_002 */ + { CR119, 0x12 }, { CR122, 0xe0 }, + { CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ + { CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ + { CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ }; static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) { int r; static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, - { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, - { ZD_CR203, 0x06 }, + { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, + { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, + { CR203, 0x06 }, { }, - { ZD_CR240, 0x80 }, + { CR240, 0x80 }, }; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -94,12 +94,12 @@ static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) /* related to antenna selection? */ if (chip->new_phy_layout) { - r = zd_iowrite16_locked(chip, 0xe1, ZD_CR9); + r = zd_iowrite16_locked(chip, 0xe1, CR9); if (r) return r; } - return zd_iowrite16_locked(chip, 0x06, ZD_CR203); + return zd_iowrite16_locked(chip, 0x06, CR203); } static int zd1211_al2230_init_hw(struct zd_rf *rf) @@ -108,40 +108,40 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs_init[] = { - { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, - { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, - { ZD_CR44, 0x33 }, { ZD_CR106, 0x2a }, { ZD_CR107, 0x1a }, - { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, { ZD_CR111, 0x2b }, - { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, { ZD_CR10, 0x89 }, + { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, + { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, + { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, + { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, + { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR17, 0x28 }, - { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 }, + { CR17, 0x28 }, + { CR26, 0x93 }, { CR34, 0x30 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR35, 0x3e }, - { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, + { CR35, 0x3e }, + { CR41, 0x24 }, { CR44, 0x32 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR46, 0x96 }, - { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, - { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, - { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 }, - { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR106, 0x24 }, - { ZD_CR107, 0x2a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x13 }, - { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, - { ZD_CR114, 0x27 }, + { CR46, 0x96 }, + { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, + { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, + { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, + { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, + { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, + { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x27 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR115, 0x24 }, - { ZD_CR116, 0x24 }, { ZD_CR117, 0xf4 }, { ZD_CR118, 0xfc }, - { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, { ZD_CR121, 0x77 }, - { ZD_CR122, 0xe0 }, { ZD_CR137, 0x88 }, { ZD_CR252, 0xff }, - { ZD_CR253, 0xff }, + { CR115, 0x24 }, + { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, + { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, + { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, + { CR253, 0xff }, }; static const struct zd_ioreq16 ioreqs_pll[] = { /* shdnb(PLL_ON)=0 */ - { ZD_CR251, 0x2f }, + { CR251, 0x2f }, /* shdnb(PLL_ON)=1 */ - { ZD_CR251, 0x3f }, - { ZD_CR138, 0x28 }, { ZD_CR203, 0x06 }, + { CR251, 0x3f }, + { CR138, 0x28 }, { CR203, 0x06 }, }; static const u32 rv1[] = { @@ -161,7 +161,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) 0x0805b6, 0x011687, 0x000688, - 0x0403b9, /* external control TX power (ZD_CR31) */ + 0x0403b9, /* external control TX power (CR31) */ 0x00dbba, 0x00099b, 0x0bdffc, @@ -221,54 +221,52 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs1[] = { - { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, - { ZD_CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ - { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, - { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, - { ZD_CR33, 0x28 }, /* 5621 */ - { ZD_CR34, 0x30 }, - { ZD_CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ - { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, - { ZD_CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ - { ZD_CR47, 0x1e }, + { CR10, 0x89 }, { CR15, 0x20 }, + { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ + { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, + { CR28, 0x3e }, { CR29, 0x00 }, + { CR33, 0x28 }, /* 5621 */ + { CR34, 0x30 }, + { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ + { CR41, 0x24 }, { CR44, 0x32 }, + { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ + { CR47, 0x1e }, /* ZD1211B 05.06.10 */ - { ZD_CR48, 0x06 }, { ZD_CR49, 0xf9 }, { ZD_CR51, 0x01 }, - { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 }, - { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 }, - { ZD_CR69, 0x28 }, - - { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, - { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, - { ZD_CR91, 0x00 }, /* 5621 */ - { ZD_CR92, 0x0a }, - { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */ - { ZD_CR99, 0x00 }, /* 5621 */ - { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, - { ZD_CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ - { ZD_CR107, 0x2a }, - { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */ - { ZD_CR110, 0x1f }, /* 4804, for 1212 new algorithm */ - { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, - { ZD_CR114, 0x27 }, - { ZD_CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) - * AL2230 - */ - { ZD_CR116, 0x24 }, - { ZD_CR117, 0xfa }, /* for 1211b */ - { ZD_CR118, 0xfa }, /* for 1211b */ - { ZD_CR119, 0x10 }, - { ZD_CR120, 0x4f }, - { ZD_CR121, 0x6c }, /* for 1211b */ - { ZD_CR122, 0xfc }, /* E0->FC at 4902 */ - { ZD_CR123, 0x57 }, /* 5623 */ - { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */ - { ZD_CR126, 0x6c }, /* 5614 */ - { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */ - { ZD_CR137, 0x50 }, /* 5614 */ - { ZD_CR138, 0xa8 }, - { ZD_CR144, 0xac }, /* 5621 */ - { ZD_CR150, 0x0d }, { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 }, + { CR48, 0x06 }, { CR49, 0xf9 }, { CR51, 0x01 }, + { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, + { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, + { CR69, 0x28 }, + + { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, + { CR87, 0x0a }, { CR89, 0x04 }, + { CR91, 0x00 }, /* 5621 */ + { CR92, 0x0a }, + { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ + { CR99, 0x00 }, /* 5621 */ + { CR101, 0x13 }, { CR102, 0x27 }, + { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ + { CR107, 0x2a }, + { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ + { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ + { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x27 }, + { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ + { CR116, 0x24 }, + { CR117, 0xfa }, /* for 1211b */ + { CR118, 0xfa }, /* for 1211b */ + { CR119, 0x10 }, + { CR120, 0x4f }, + { CR121, 0x6c }, /* for 1211b */ + { CR122, 0xfc }, /* E0->FC at 4902 */ + { CR123, 0x57 }, /* 5623 */ + { CR125, 0xad }, /* 4804, for 1212 new algorithm */ + { CR126, 0x6c }, /* 5614 */ + { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ + { CR137, 0x50 }, /* 5614 */ + { CR138, 0xa8 }, + { CR144, 0xac }, /* 5621 */ + { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 }, }; static const u32 rv1[] = { @@ -286,7 +284,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) 0x6da010, /* Reg6 update for MP versio */ 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */ 0x116000, - 0x9dc020, /* External control TX power (ZD_CR31) */ + 0x9dc020, /* External control TX power (CR31) */ 0x5ddb00, /* RegA update for MP version */ 0xd99000, /* RegB update for MP version */ 0x3ffbd0, /* RegC update for MP version */ @@ -297,8 +295,8 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) }; static const struct zd_ioreq16 ioreqs2[] = { - { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ - { ZD_CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ + { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ + { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ }; static const u32 rv3[] = { @@ -310,7 +308,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) static const struct zd_ioreq16 ioreqs3[] = { /* related to 6M band edge patching, happens unconditionally */ - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, }; r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, @@ -363,8 +361,8 @@ static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel) const u32 *rv = zd1211_al2230_table[channel-1]; struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR138, 0x28 }, - { ZD_CR203, 0x06 }, + { CR138, 0x28 }, + { CR203, 0x06 }, }; r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); @@ -395,8 +393,8 @@ static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x00 }, - { ZD_CR251, 0x3f }, + { CR11, 0x00 }, + { CR251, 0x3f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -406,8 +404,8 @@ static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x00 }, - { ZD_CR251, 0x7f }, + { CR11, 0x00 }, + { CR251, 0x7f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -417,8 +415,8 @@ static int al2230_switch_radio_off(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x04 }, - { ZD_CR251, 0x2f }, + { CR11, 0x04 }, + { CR251, 0x2f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c index 385c670d1293..65095d661e6b 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c @@ -68,19 +68,19 @@ static const u32 rv_init2[] = { }; static const struct zd_ioreq16 ioreqs_sw[] = { - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, - { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR38, 0x38 }, { CR136, 0xdf }, }; static int zd1211b_al7230b_finalize(struct zd_chip *chip) { int r; static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, - { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, - { ZD_CR203, 0x04 }, + { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, + { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, + { CR203, 0x04 }, { }, - { ZD_CR240, 0x80 }, + { CR240, 0x80 }, }; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -89,12 +89,12 @@ static int zd1211b_al7230b_finalize(struct zd_chip *chip) if (chip->new_phy_layout) { /* antenna selection? */ - r = zd_iowrite16_locked(chip, 0xe5, ZD_CR9); + r = zd_iowrite16_locked(chip, 0xe5, CR9); if (r) return r; } - return zd_iowrite16_locked(chip, 0x04, ZD_CR203); + return zd_iowrite16_locked(chip, 0x04, CR203); } static int zd1211_al7230b_init_hw(struct zd_rf *rf) @@ -106,66 +106,66 @@ static int zd1211_al7230b_init_hw(struct zd_rf *rf) * specified */ static const struct zd_ioreq16 ioreqs_1[] = { /* This one is 7230-specific, and happens before the rest */ - { ZD_CR240, 0x57 }, + { CR240, 0x57 }, { }, - { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, - { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, - { ZD_CR44, 0x33 }, + { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, + { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, + { CR44, 0x33 }, /* This value is different for 7230 (was: 0x2a) */ - { ZD_CR106, 0x22 }, - { ZD_CR107, 0x1a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, - { ZD_CR111, 0x2b }, { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, + { CR106, 0x22 }, + { CR107, 0x1a }, { CR109, 0x09 }, { CR110, 0x27 }, + { CR111, 0x2b }, { CR112, 0x2b }, { CR119, 0x0a }, /* This happened further down in AL2230, * and the value changed (was: 0xe0) */ - { ZD_CR122, 0xfc }, - { ZD_CR10, 0x89 }, + { CR122, 0xfc }, + { CR10, 0x89 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR17, 0x28 }, - { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 }, + { CR17, 0x28 }, + { CR26, 0x93 }, { CR34, 0x30 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR35, 0x3e }, - { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, + { CR35, 0x3e }, + { CR41, 0x24 }, { CR44, 0x32 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR46, 0x96 }, - { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, - { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, - { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, + { CR46, 0x96 }, + { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, + { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, + { CR92, 0x0a }, { CR99, 0x28 }, /* This value is different for 7230 (was: 0x00) */ - { ZD_CR100, 0x02 }, - { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, + { CR100, 0x02 }, + { CR101, 0x13 }, { CR102, 0x27 }, /* This value is different for 7230 (was: 0x24) */ - { ZD_CR106, 0x22 }, + { CR106, 0x22 }, /* This value is different for 7230 (was: 0x2a) */ - { ZD_CR107, 0x3f }, - { ZD_CR109, 0x09 }, + { CR107, 0x3f }, + { CR109, 0x09 }, /* This value is different for 7230 (was: 0x13) */ - { ZD_CR110, 0x1f }, - { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, - { ZD_CR114, 0x27 }, + { CR110, 0x1f }, + { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x27 }, /* for newest (3rd cut) AL2300 */ - { ZD_CR115, 0x24 }, + { CR115, 0x24 }, /* This value is different for 7230 (was: 0x24) */ - { ZD_CR116, 0x3f }, + { CR116, 0x3f }, /* This value is different for 7230 (was: 0xf4) */ - { ZD_CR117, 0xfa }, - { ZD_CR118, 0xfc }, { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, - { ZD_CR121, 0x77 }, { ZD_CR137, 0x88 }, + { CR117, 0xfa }, + { CR118, 0xfc }, { CR119, 0x10 }, { CR120, 0x4f }, + { CR121, 0x77 }, { CR137, 0x88 }, /* This one is 7230-specific */ - { ZD_CR138, 0xa8 }, + { CR138, 0xa8 }, /* This value is different for 7230 (was: 0xff) */ - { ZD_CR252, 0x34 }, + { CR252, 0x34 }, /* This value is different for 7230 (was: 0xff) */ - { ZD_CR253, 0x34 }, + { CR253, 0x34 }, /* PLL_OFF */ - { ZD_CR251, 0x2f }, + { CR251, 0x2f }, }; static const struct zd_ioreq16 ioreqs_2[] = { - { ZD_CR251, 0x3f }, /* PLL_ON */ - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, - { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, + { CR251, 0x3f }, /* PLL_ON */ + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR38, 0x38 }, { CR136, 0xdf }, }; r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); @@ -192,10 +192,10 @@ static int zd1211_al7230b_init_hw(struct zd_rf *rf) if (r) return r; - r = zd_iowrite16_locked(chip, 0x06, ZD_CR203); + r = zd_iowrite16_locked(chip, 0x06, CR203); if (r) return r; - r = zd_iowrite16_locked(chip, 0x80, ZD_CR240); + r = zd_iowrite16_locked(chip, 0x80, CR240); if (r) return r; @@ -208,79 +208,79 @@ static int zd1211b_al7230b_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs_1[] = { - { ZD_CR240, 0x57 }, { ZD_CR9, 0x9 }, + { CR240, 0x57 }, { CR9, 0x9 }, { }, - { ZD_CR10, 0x8b }, { ZD_CR15, 0x20 }, - { ZD_CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ - { ZD_CR20, 0x10 }, /* 4N25->Stone Request */ - { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, - { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, - { ZD_CR33, 0x28 }, /* 5613 */ - { ZD_CR34, 0x30 }, - { ZD_CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ - { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, - { ZD_CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ - { ZD_CR47, 0x1e }, + { CR10, 0x8b }, { CR15, 0x20 }, + { CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ + { CR20, 0x10 }, /* 4N25->Stone Request */ + { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, + { CR28, 0x3e }, { CR29, 0x00 }, + { CR33, 0x28 }, /* 5613 */ + { CR34, 0x30 }, + { CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ + { CR41, 0x24 }, { CR44, 0x32 }, + { CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ + { CR47, 0x1e }, /* ZD1215 5610 */ - { ZD_CR48, 0x00 }, { ZD_CR49, 0x00 }, { ZD_CR51, 0x01 }, - { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 }, - { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 }, - { ZD_CR69, 0x28 }, - - { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, - { ZD_CR87, 0x0A }, { ZD_CR89, 0x04 }, - { ZD_CR90, 0x58 }, /* 5112 */ - { ZD_CR91, 0x00 }, /* 5613 */ - { ZD_CR92, 0x0a }, - { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */ - { ZD_CR99, 0x00 }, { ZD_CR100, 0x02 }, { ZD_CR101, 0x13 }, - { ZD_CR102, 0x27 }, - { ZD_CR106, 0x20 }, /* change to 0x24 for AL7230B */ - { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */ - { ZD_CR112, 0x1f }, + { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, + { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, + { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, + { CR69, 0x28 }, + + { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, + { CR87, 0x0A }, { CR89, 0x04 }, + { CR90, 0x58 }, /* 5112 */ + { CR91, 0x00 }, /* 5613 */ + { CR92, 0x0a }, + { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ + { CR99, 0x00 }, { CR100, 0x02 }, { CR101, 0x13 }, + { CR102, 0x27 }, + { CR106, 0x20 }, /* change to 0x24 for AL7230B */ + { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ + { CR112, 0x1f }, }; static const struct zd_ioreq16 ioreqs_new_phy[] = { - { ZD_CR107, 0x28 }, - { ZD_CR110, 0x1f }, /* 5127, 0x13->0x1f */ - { ZD_CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ - { ZD_CR116, 0x2a }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x12 }, - { ZD_CR121, 0x6c }, /* 5613 */ + { CR107, 0x28 }, + { CR110, 0x1f }, /* 5127, 0x13->0x1f */ + { CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ + { CR116, 0x2a }, { CR118, 0xfa }, { CR119, 0x12 }, + { CR121, 0x6c }, /* 5613 */ }; static const struct zd_ioreq16 ioreqs_old_phy[] = { - { ZD_CR107, 0x24 }, - { ZD_CR110, 0x13 }, /* 5127, 0x13->0x1f */ - { ZD_CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ - { ZD_CR116, 0x24 }, { ZD_CR118, 0xfc }, { ZD_CR119, 0x11 }, - { ZD_CR121, 0x6a }, /* 5613 */ + { CR107, 0x24 }, + { CR110, 0x13 }, /* 5127, 0x13->0x1f */ + { CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ + { CR116, 0x24 }, { CR118, 0xfc }, { CR119, 0x11 }, + { CR121, 0x6a }, /* 5613 */ }; static const struct zd_ioreq16 ioreqs_2[] = { - { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x24 }, - { ZD_CR117, 0xfa }, { ZD_CR120, 0x4f }, - { ZD_CR122, 0xfc }, /* E0->FCh at 4901 */ - { ZD_CR123, 0x57 }, /* 5613 */ - { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */ - { ZD_CR126, 0x6c }, /* 5613 */ - { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */ - { ZD_CR130, 0x10 }, - { ZD_CR131, 0x00 }, /* 5112 */ - { ZD_CR137, 0x50 }, /* 5613 */ - { ZD_CR138, 0xa8 }, /* 5112 */ - { ZD_CR144, 0xac }, /* 5613 */ - { ZD_CR148, 0x40 }, /* 5112 */ - { ZD_CR149, 0x40 }, /* 4O07, 50->40 */ - { ZD_CR150, 0x1a }, /* 5112, 0C->1A */ - { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 }, - { ZD_CR251, 0x2f }, /* PLL_OFF */ + { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x24 }, + { CR117, 0xfa }, { CR120, 0x4f }, + { CR122, 0xfc }, /* E0->FCh at 4901 */ + { CR123, 0x57 }, /* 5613 */ + { CR125, 0xad }, /* 4804, for 1212 new algorithm */ + { CR126, 0x6c }, /* 5613 */ + { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ + { CR130, 0x10 }, + { CR131, 0x00 }, /* 5112 */ + { CR137, 0x50 }, /* 5613 */ + { CR138, 0xa8 }, /* 5112 */ + { CR144, 0xac }, /* 5613 */ + { CR148, 0x40 }, /* 5112 */ + { CR149, 0x40 }, /* 4O07, 50->40 */ + { CR150, 0x1a }, /* 5112, 0C->1A */ + { CR252, 0x34 }, { CR253, 0x34 }, + { CR251, 0x2f }, /* PLL_OFF */ }; static const struct zd_ioreq16 ioreqs_3[] = { - { ZD_CR251, 0x7f }, /* PLL_ON */ - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, - { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, + { CR251, 0x7f }, /* PLL_ON */ + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR38, 0x38 }, { CR136, 0xdf }, }; r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); @@ -331,16 +331,16 @@ static int zd1211_al7230b_set_channel(struct zd_rf *rf, u8 channel) static const struct zd_ioreq16 ioreqs[] = { /* PLL_ON */ - { ZD_CR251, 0x3f }, - { ZD_CR203, 0x06 }, { ZD_CR240, 0x08 }, + { CR251, 0x3f }, + { CR203, 0x06 }, { CR240, 0x08 }, }; - r = zd_iowrite16_locked(chip, 0x57, ZD_CR240); + r = zd_iowrite16_locked(chip, 0x57, CR240); if (r) return r; /* PLL_OFF */ - r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251); + r = zd_iowrite16_locked(chip, 0x2f, CR251); if (r) return r; @@ -376,15 +376,15 @@ static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel) const u32 *rv = chan_rv[channel-1]; struct zd_chip *chip = zd_rf_to_chip(rf); - r = zd_iowrite16_locked(chip, 0x57, ZD_CR240); + r = zd_iowrite16_locked(chip, 0x57, CR240); if (r) return r; - r = zd_iowrite16_locked(chip, 0xe4, ZD_CR9); + r = zd_iowrite16_locked(chip, 0xe4, CR9); if (r) return r; /* PLL_OFF */ - r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251); + r = zd_iowrite16_locked(chip, 0x2f, CR251); if (r) return r; r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); @@ -410,7 +410,7 @@ static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel) if (r) return r; - r = zd_iowrite16_locked(chip, 0x7f, ZD_CR251); + r = zd_iowrite16_locked(chip, 0x7f, CR251); if (r) return r; @@ -421,8 +421,8 @@ static int zd1211_al7230b_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x00 }, - { ZD_CR251, 0x3f }, + { CR11, 0x00 }, + { CR251, 0x3f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -432,8 +432,8 @@ static int zd1211b_al7230b_switch_radio_on(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x00 }, - { ZD_CR251, 0x7f }, + { CR11, 0x00 }, + { CR251, 0x7f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -443,8 +443,8 @@ static int al7230b_switch_radio_off(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x04 }, - { ZD_CR251, 0x2f }, + { CR11, 0x04 }, + { CR251, 0x2f }, }; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); @@ -456,7 +456,7 @@ static int zd1211b_al7230b_patch_6m(struct zd_rf *rf, u8 channel) { struct zd_chip *chip = zd_rf_to_chip(rf); struct zd_ioreq16 ioreqs[] = { - { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, + { CR128, 0x14 }, { CR129, 0x12 }, }; /* FIXME: Channel 11 is not the edge for all regulatory domains. */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c index 032542614259..0597d862fbd2 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -152,44 +152,44 @@ static int rf2959_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR2, 0x1E }, { ZD_CR9, 0x20 }, { ZD_CR10, 0x89 }, - { ZD_CR11, 0x00 }, { ZD_CR15, 0xD0 }, { ZD_CR17, 0x68 }, - { ZD_CR19, 0x4a }, { ZD_CR20, 0x0c }, { ZD_CR21, 0x0E }, - { ZD_CR23, 0x48 }, + { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, + { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, + { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, + { CR23, 0x48 }, /* normal size for cca threshold */ - { ZD_CR24, 0x14 }, - /* { ZD_CR24, 0x20 }, */ - { ZD_CR26, 0x90 }, { ZD_CR27, 0x30 }, { ZD_CR29, 0x20 }, - { ZD_CR31, 0xb2 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x28 }, - { ZD_CR38, 0x30 }, { ZD_CR34, 0x0f }, { ZD_CR35, 0xF0 }, - { ZD_CR41, 0x2a }, { ZD_CR46, 0x7F }, { ZD_CR47, 0x1E }, - { ZD_CR51, 0xc5 }, { ZD_CR52, 0xc5 }, { ZD_CR53, 0xc5 }, - { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, - { ZD_CR82, 0x00 }, { ZD_CR83, 0x24 }, { ZD_CR84, 0x04 }, - { ZD_CR85, 0x00 }, { ZD_CR86, 0x10 }, { ZD_CR87, 0x2A }, - { ZD_CR88, 0x10 }, { ZD_CR89, 0x24 }, { ZD_CR90, 0x18 }, - /* { ZD_CR91, 0x18 }, */ + { CR24, 0x14 }, + /* { CR24, 0x20 }, */ + { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, + { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, + { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, + { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, + { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, + { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, + { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, + { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, + { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, + /* { CR91, 0x18 }, */ /* should solve continous CTS frame problems */ - { ZD_CR91, 0x00 }, - { ZD_CR92, 0x0a }, { ZD_CR93, 0x00 }, { ZD_CR94, 0x01 }, - { ZD_CR95, 0x00 }, { ZD_CR96, 0x40 }, { ZD_CR97, 0x37 }, - { ZD_CR98, 0x05 }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 }, - { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, - { ZD_CR104, 0x18 }, { ZD_CR105, 0x12 }, + { CR91, 0x00 }, + { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, + { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, + { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, + { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, + { CR104, 0x18 }, { CR105, 0x12 }, /* normal size */ - { ZD_CR106, 0x1a }, - /* { ZD_CR106, 0x22 }, */ - { ZD_CR107, 0x24 }, { ZD_CR108, 0x0a }, { ZD_CR109, 0x13 }, - { ZD_CR110, 0x2F }, { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, - { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x40 }, - { ZD_CR116, 0x40 }, { ZD_CR117, 0xF0 }, { ZD_CR118, 0xF0 }, - { ZD_CR119, 0x16 }, + { CR106, 0x1a }, + /* { CR106, 0x22 }, */ + { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, + { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, + { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, + { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, + { CR119, 0x16 }, /* no TX continuation */ - { ZD_CR122, 0x00 }, - /* { ZD_CR122, 0xff }, */ - { ZD_CR127, 0x03 }, { ZD_CR131, 0x08 }, { ZD_CR138, 0x28 }, - { ZD_CR148, 0x44 }, { ZD_CR150, 0x10 }, { ZD_CR169, 0xBB }, - { ZD_CR170, 0xBB }, + { CR122, 0x00 }, + /* { CR122, 0xff }, */ + { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, + { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, + { CR170, 0xBB }, }; static const u32 rv[] = { @@ -210,7 +210,7 @@ static int rf2959_init_hw(struct zd_rf *rf) */ 0x294128, /* internal power */ /* 0x28252c, */ /* External control TX power */ - /* ZD_CR31_CCK, ZD_CR51_6-36M, ZD_CR52_48M, ZD_CR53_54M */ + /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ 0x2c0000, 0x300000, 0x340000, /* REG13(0xD) */ @@ -245,8 +245,8 @@ static int rf2959_set_channel(struct zd_rf *rf, u8 channel) static int rf2959_switch_radio_on(struct zd_rf *rf) { static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR10, 0x89 }, - { ZD_CR11, 0x00 }, + { CR10, 0x89 }, + { CR11, 0x00 }, }; struct zd_chip *chip = zd_rf_to_chip(rf); @@ -256,8 +256,8 @@ static int rf2959_switch_radio_on(struct zd_rf *rf) static int rf2959_switch_radio_off(struct zd_rf *rf) { static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR10, 0x15 }, - { ZD_CR11, 0x81 }, + { CR10, 0x15 }, + { CR11, 0x81 }, }; struct zd_chip *chip = zd_rf_to_chip(rf); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c index 860b0af7dc3e..9e74eb1b67d5 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c @@ -314,44 +314,42 @@ static int uw2453_init_hw(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, - { ZD_CR17, 0x28 }, /* 6112 no change */ - { ZD_CR23, 0x38 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, - { ZD_CR27, 0x15 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, - { ZD_CR33, 0x28 }, { ZD_CR34, 0x30 }, - { ZD_CR35, 0x43 }, /* 6112 3e->43 */ - { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, - { ZD_CR46, 0x92 }, /* 6112 96->92 */ - { ZD_CR47, 0x1e }, - { ZD_CR48, 0x04 }, /* 5602 Roger */ - { ZD_CR49, 0xfa }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, - { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, - { ZD_CR91, 0x00 }, { ZD_CR92, 0x0a }, { ZD_CR98, 0x8d }, - { ZD_CR99, 0x28 }, { ZD_CR100, 0x02 }, - { ZD_CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ - { ZD_CR102, 0x27 }, - { ZD_CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f - * 6221 1f->1c - */ - { ZD_CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ - { ZD_CR109, 0x13 }, - { ZD_CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ - { ZD_CR111, 0x13 }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, - { ZD_CR114, 0x23 }, /* 6221 27->23 */ - { ZD_CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ - { ZD_CR116, 0x24 }, /* 6220 1c->24 */ - { ZD_CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ - { ZD_CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ - { ZD_CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ - { ZD_CR120, 0x4f }, - { ZD_CR121, 0x1f }, /* 6220 4f->1f */ - { ZD_CR122, 0xf0 }, { ZD_CR123, 0x57 }, { ZD_CR125, 0xad }, - { ZD_CR126, 0x6c }, { ZD_CR127, 0x03 }, - { ZD_CR128, 0x14 }, /* 6302 12->11 */ - { ZD_CR129, 0x12 }, /* 6301 10->0f */ - { ZD_CR130, 0x10 }, { ZD_CR137, 0x50 }, { ZD_CR138, 0xa8 }, - { ZD_CR144, 0xac }, { ZD_CR146, 0x20 }, { ZD_CR252, 0xff }, - { ZD_CR253, 0xff }, + { CR10, 0x89 }, { CR15, 0x20 }, + { CR17, 0x28 }, /* 6112 no change */ + { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 }, + { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 }, + { CR33, 0x28 }, { CR34, 0x30 }, + { CR35, 0x43 }, /* 6112 3e->43 */ + { CR41, 0x24 }, { CR44, 0x32 }, + { CR46, 0x92 }, /* 6112 96->92 */ + { CR47, 0x1e }, + { CR48, 0x04 }, /* 5602 Roger */ + { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 }, + { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, + { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d }, + { CR99, 0x28 }, { CR100, 0x02 }, + { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ + { CR102, 0x27 }, + { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */ + { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ + { CR109, 0x13 }, + { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ + { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x23 }, /* 6221 27->23 */ + { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ + { CR116, 0x24 }, /* 6220 1c->24 */ + { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ + { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ + { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ + { CR120, 0x4f }, + { CR121, 0x1f }, /* 6220 4f->1f */ + { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad }, + { CR126, 0x6c }, { CR127, 0x03 }, + { CR128, 0x14 }, /* 6302 12->11 */ + { CR129, 0x12 }, /* 6301 10->0f */ + { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 }, + { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff }, + { CR253, 0xff }, }; static const u32 rv[] = { @@ -435,7 +433,7 @@ static int uw2453_init_hw(struct zd_rf *rf) * the one that produced a lock. */ UW2453_PRIV(rf)->config = found_config + 1; - return zd_iowrite16_locked(chip, 0x06, ZD_CR203); + return zd_iowrite16_locked(chip, 0x06, CR203); } static int uw2453_set_channel(struct zd_rf *rf, u8 channel) @@ -447,8 +445,8 @@ static int uw2453_set_channel(struct zd_rf *rf, u8 channel) struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, - { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, + { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, + { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, }; r = uw2453_synth_set_channel(chip, channel, autocal); @@ -476,7 +474,7 @@ static int uw2453_set_channel(struct zd_rf *rf, u8 channel) if (r) return r; - return zd_iowrite16_locked(chip, 0x06, ZD_CR203); + return zd_iowrite16_locked(chip, 0x06, CR203); } static int uw2453_switch_radio_on(struct zd_rf *rf) @@ -484,7 +482,7 @@ static int uw2453_switch_radio_on(struct zd_rf *rf) int r; struct zd_chip *chip = zd_rf_to_chip(rf); struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x00 }, { ZD_CR251, 0x3f }, + { CR11, 0x00 }, { CR251, 0x3f }, }; /* enter RXTX mode */ @@ -503,7 +501,7 @@ static int uw2453_switch_radio_off(struct zd_rf *rf) int r; struct zd_chip *chip = zd_rf_to_chip(rf); static const struct zd_ioreq16 ioreqs[] = { - { ZD_CR11, 0x04 }, { ZD_CR251, 0x2f }, + { CR11, 0x04 }, { CR251, 0x2f }, }; /* enter IDLE mode */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 0e819943b9e4..ab607bbd6291 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1893,10 +1893,10 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); - r = zd_usb_ioread16(usb, &bit_value_template, ZD_CR203); + r = zd_usb_ioread16(usb, &bit_value_template, CR203); if (r) { dev_dbg_f(zd_usb_dev(usb), - "error %d: Couldn't read ZD_CR203\n", r); + "error %d: Couldn't read CR203\n", r); return r; } bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.h b/trunk/drivers/net/wireless/zd1211rw/zd_usb.h index bf942843b733..325d0f989257 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.h @@ -109,7 +109,7 @@ struct usb_req_rfwrite { __le16 bits; /* RF2595: 24 */ __le16 bit_values[0]; - /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ + /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ } __packed; /* USB interrupt */ diff --git a/trunk/drivers/ssb/driver_chipcommon.c b/trunk/drivers/ssb/driver_chipcommon.c index b4b3733aefcf..7c031fdc8205 100644 --- a/trunk/drivers/ssb/driver_chipcommon.c +++ b/trunk/drivers/ssb/driver_chipcommon.c @@ -260,12 +260,6 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) if (cc->dev->id.revision >= 11) cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); - - if (cc->dev->id.revision >= 20) { - chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); - chipco_write32(cc, SSB_CHIPCO_GPIOPULLDOWN, 0); - } - ssb_pmu_init(cc); chipco_powercontrol_init(cc); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); diff --git a/trunk/drivers/ssb/driver_chipcommon_pmu.c b/trunk/drivers/ssb/driver_chipcommon_pmu.c index 305ade7825f7..5732bb2c3578 100644 --- a/trunk/drivers/ssb/driver_chipcommon_pmu.c +++ b/trunk/drivers/ssb/driver_chipcommon_pmu.c @@ -423,8 +423,6 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) switch (bus->chip_id) { case 0x4312: - min_msk = 0xCBB; - break; case 0x4322: /* We keep the default settings: * min_msk = 0xCBB diff --git a/trunk/drivers/ssb/driver_pcicore.c b/trunk/drivers/ssb/driver_pcicore.c index 8fde1220bc89..0e8d35224614 100644 --- a/trunk/drivers/ssb/driver_pcicore.c +++ b/trunk/drivers/ssb/driver_pcicore.c @@ -15,13 +15,6 @@ #include "ssb_private.h" -static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address); -static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data); -static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); -static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, - u8 address, u16 data); - -static void ssb_commit_settings(struct ssb_bus *bus); static inline u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) @@ -410,107 +403,6 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) } #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ -/************************************************** - * Workarounds. - **************************************************/ - -static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) -{ - u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0)); - if (((tmp & 0xF000) >> 12) != pc->dev->core_index) { - tmp &= ~0xF000; - tmp |= (pc->dev->core_index << 12); - pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp); - } -} - -static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc) -{ - return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; -} - -static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc) -{ - const u8 serdes_pll_device = 0x1D; - const u8 serdes_rx_device = 0x1F; - u16 tmp; - - ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, - ssb_pcicore_polarity_workaround(pc)); - tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); - if (tmp & 0x4000) - ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); -} - -static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc) -{ - struct ssb_device *pdev = pc->dev; - struct ssb_bus *bus = pdev->bus; - u32 tmp; - - tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); - tmp |= SSB_PCICORE_SBTOPCI_PREF; - tmp |= SSB_PCICORE_SBTOPCI_BURST; - pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); - - if (pdev->id.revision < 5) { - tmp = ssb_read32(pdev, SSB_IMCFGLO); - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 2; - tmp &= ~SSB_IMCFGLO_REQTO; - tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; - ssb_write32(pdev, SSB_IMCFGLO, tmp); - ssb_commit_settings(bus); - } else if (pdev->id.revision >= 11) { - tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); - tmp |= SSB_PCICORE_SBTOPCI_MRM; - pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); - } -} - -static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) -{ - u32 tmp; - u8 rev = pc->dev->id.revision; - - if (rev == 0 || rev == 1) { - /* TLP Workaround register. */ - tmp = ssb_pcie_read(pc, 0x4); - tmp |= 0x8; - ssb_pcie_write(pc, 0x4, tmp); - } - if (rev == 1) { - /* DLLP Link Control register. */ - tmp = ssb_pcie_read(pc, 0x100); - tmp |= 0x40; - ssb_pcie_write(pc, 0x100, tmp); - } - - if (rev == 0) { - const u8 serdes_rx_device = 0x1F; - - ssb_pcie_mdio_write(pc, serdes_rx_device, - 2 /* Timer */, 0x8128); - ssb_pcie_mdio_write(pc, serdes_rx_device, - 6 /* CDR */, 0x0100); - ssb_pcie_mdio_write(pc, serdes_rx_device, - 7 /* CDR BW */, 0x1466); - } else if (rev == 3 || rev == 4 || rev == 5) { - /* TODO: DLLP Power Management Threshold */ - ssb_pcicore_serdes_workaround(pc); - /* TODO: ASPM */ - } else if (rev == 7) { - /* TODO: No PLL down */ - } - - if (rev >= 6) { - /* Miscellaneous Configuration Fixup */ - tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(5)); - if (!(tmp & 0x8000)) - pcicore_write16(pc, SSB_PCICORE_SPROM(5), - tmp | 0x8000); - } -} /************************************************** * Generic and Clientmode operation code. @@ -525,14 +417,14 @@ static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) void ssb_pcicore_init(struct ssb_pcicore *pc) { struct ssb_device *dev = pc->dev; + struct ssb_bus *bus; if (!dev) return; + bus = dev->bus; if (!ssb_device_is_enabled(dev)) ssb_device_enable(dev, 0); - ssb_pcicore_fix_sprom_core_index(pc); - #ifdef CONFIG_SSB_PCICORE_HOSTMODE pc->hostmode = pcicore_is_in_hostmode(pc); if (pc->hostmode) @@ -540,11 +432,6 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ if (!pc->hostmode) ssb_pcicore_init_clientmode(pc); - - /* Additional always once-executed workarounds */ - ssb_pcicore_serdes_workaround(pc); - /* TODO: ASPM */ - /* TODO: Clock Request Update */ } static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) @@ -559,75 +446,11 @@ static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data) pcicore_write32(pc, 0x134, data); } -static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) -{ - const u16 mdio_control = 0x128; - const u16 mdio_data = 0x12C; - u32 v; - int i; - - v = (1 << 30); /* Start of Transaction */ - v |= (1 << 28); /* Write Transaction */ - v |= (1 << 17); /* Turnaround */ - v |= (0x1F << 18); - v |= (phy << 4); - pcicore_write32(pc, mdio_data, v); - - udelay(10); - for (i = 0; i < 200; i++) { - v = pcicore_read32(pc, mdio_control); - if (v & 0x100 /* Trans complete */) - break; - msleep(1); - } -} - -static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) -{ - const u16 mdio_control = 0x128; - const u16 mdio_data = 0x12C; - int max_retries = 10; - u16 ret = 0; - u32 v; - int i; - - v = 0x80; /* Enable Preamble Sequence */ - v |= 0x2; /* MDIO Clock Divisor */ - pcicore_write32(pc, mdio_control, v); - - if (pc->dev->id.revision >= 10) { - max_retries = 200; - ssb_pcie_mdio_set_phy(pc, device); - } - - v = (1 << 30); /* Start of Transaction */ - v |= (1 << 29); /* Read Transaction */ - v |= (1 << 17); /* Turnaround */ - if (pc->dev->id.revision < 10) - v |= (u32)device << 22; - v |= (u32)address << 18; - pcicore_write32(pc, mdio_data, v); - /* Wait for the device to complete the transaction */ - udelay(10); - for (i = 0; i < max_retries; i++) { - v = pcicore_read32(pc, mdio_control); - if (v & 0x100 /* Trans complete */) { - udelay(10); - ret = pcicore_read32(pc, mdio_data); - break; - } - msleep(1); - } - pcicore_write32(pc, mdio_control, 0); - return ret; -} - static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, u8 address, u16 data) { const u16 mdio_control = 0x128; const u16 mdio_data = 0x12C; - int max_retries = 10; u32 v; int i; @@ -635,22 +458,16 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, v |= 0x2; /* MDIO Clock Divisor */ pcicore_write32(pc, mdio_control, v); - if (pc->dev->id.revision >= 10) { - max_retries = 200; - ssb_pcie_mdio_set_phy(pc, device); - } - v = (1 << 30); /* Start of Transaction */ v |= (1 << 28); /* Write Transaction */ v |= (1 << 17); /* Turnaround */ - if (pc->dev->id.revision < 10) - v |= (u32)device << 22; + v |= (u32)device << 22; v |= (u32)address << 18; v |= data; pcicore_write32(pc, mdio_data, v); /* Wait for the device to complete the transaction */ udelay(10); - for (i = 0; i < max_retries; i++) { + for (i = 0; i < 10; i++) { v = pcicore_read32(pc, mdio_control); if (v & 0x100 /* Trans complete */) break; @@ -733,10 +550,48 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, if (pc->setup_done) goto out; if (pdev->id.coreid == SSB_DEV_PCI) { - ssb_pcicore_pci_setup_workarounds(pc); + tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); + tmp |= SSB_PCICORE_SBTOPCI_PREF; + tmp |= SSB_PCICORE_SBTOPCI_BURST; + pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); + + if (pdev->id.revision < 5) { + tmp = ssb_read32(pdev, SSB_IMCFGLO); + tmp &= ~SSB_IMCFGLO_SERTO; + tmp |= 2; + tmp &= ~SSB_IMCFGLO_REQTO; + tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; + ssb_write32(pdev, SSB_IMCFGLO, tmp); + ssb_commit_settings(bus); + } else if (pdev->id.revision >= 11) { + tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); + tmp |= SSB_PCICORE_SBTOPCI_MRM; + pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); + } } else { WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); - ssb_pcicore_pcie_setup_workarounds(pc); + //TODO: Better make defines for all these magic PCIE values. + if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { + /* TLP Workaround register. */ + tmp = ssb_pcie_read(pc, 0x4); + tmp |= 0x8; + ssb_pcie_write(pc, 0x4, tmp); + } + if (pdev->id.revision == 0) { + const u8 serdes_rx_device = 0x1F; + + ssb_pcie_mdio_write(pc, serdes_rx_device, + 2 /* Timer */, 0x8128); + ssb_pcie_mdio_write(pc, serdes_rx_device, + 6 /* CDR */, 0x0100); + ssb_pcie_mdio_write(pc, serdes_rx_device, + 7 /* CDR BW */, 0x1466); + } else if (pdev->id.revision == 1) { + /* DLLP Link Control register. */ + tmp = ssb_pcie_read(pc, 0x100); + tmp |= 0x40; + ssb_pcie_write(pc, 0x100, tmp); + } } pc->setup_done = 1; out: diff --git a/trunk/drivers/ssb/main.c b/trunk/drivers/ssb/main.c index ad3da93a428c..e05ba6eefc7e 100644 --- a/trunk/drivers/ssb/main.c +++ b/trunk/drivers/ssb/main.c @@ -1117,22 +1117,23 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev) { u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV; - /* The REJECT bit seems to be different for Backplane rev 2.3 */ + /* The REJECT bit changed position in TMSLOW between + * Backplane revisions. */ switch (rev) { case SSB_IDLOW_SSBREV_22: - case SSB_IDLOW_SSBREV_24: - case SSB_IDLOW_SSBREV_26: - return SSB_TMSLOW_REJECT; + return SSB_TMSLOW_REJECT_22; case SSB_IDLOW_SSBREV_23: return SSB_TMSLOW_REJECT_23; - case SSB_IDLOW_SSBREV_25: /* TODO - find the proper REJECT bit */ + case SSB_IDLOW_SSBREV_24: /* TODO - find the proper REJECT bits */ + case SSB_IDLOW_SSBREV_25: /* same here */ + case SSB_IDLOW_SSBREV_26: /* same here */ case SSB_IDLOW_SSBREV_27: /* same here */ - return SSB_TMSLOW_REJECT; /* this is a guess */ + return SSB_TMSLOW_REJECT_23; /* this is a guess */ default: printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); WARN_ON(1); } - return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); + return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23); } int ssb_device_is_enabled(struct ssb_device *dev) @@ -1308,20 +1309,20 @@ EXPORT_SYMBOL(ssb_bus_may_powerdown); int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) { + struct ssb_chipcommon *cc; int err; enum ssb_clkmode mode; err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); if (err) goto error; + cc = &bus->chipco; + mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; + ssb_chipco_set_clockmode(cc, mode); #ifdef CONFIG_SSB_DEBUG bus->powered_up = 1; #endif - - mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; - ssb_chipco_set_clockmode(&bus->chipco, mode); - return 0; error: ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); diff --git a/trunk/drivers/ssb/scan.c b/trunk/drivers/ssb/scan.c index 7dca719fbcfb..29884c00c4d5 100644 --- a/trunk/drivers/ssb/scan.c +++ b/trunk/drivers/ssb/scan.c @@ -307,7 +307,7 @@ int ssb_bus_scan(struct ssb_bus *bus, } else { if (bus->bustype == SSB_BUSTYPE_PCI) { bus->chip_id = pcidev_to_chipid(bus->host_pci); - pci_read_config_byte(bus->host_pci, PCI_REVISION_ID, + pci_read_config_word(bus->host_pci, PCI_REVISION_ID, &bus->chip_rev); bus->chip_package = 0; } else { diff --git a/trunk/include/linux/ath9k_platform.h b/trunk/include/linux/ath9k_platform.h index 60a7c49dcb49..b847fc7b93f9 100644 --- a/trunk/include/linux/ath9k_platform.h +++ b/trunk/include/linux/ath9k_platform.h @@ -23,13 +23,6 @@ struct ath9k_platform_data { u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; - u8 *macaddr; - - int led_pin; - u32 gpio_mask; - u32 gpio_val; - - bool is_clk_25mhz; }; #endif /* _LINUX_ATH9K_PLATFORM_H */ diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 79690b710665..2d1c6117d92c 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -884,15 +884,6 @@ struct ieee80211_ht_cap { #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 -/* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */ -#define IEEE80211_HT_EXT_CAP_PCO 0x0001 -#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 -#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 -#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 -#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 -#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 -#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 - /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index be8df57b789d..30022189104d 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -410,16 +410,6 @@ * notification. This event is used to indicate that an unprotected * disassociation frame was dropped when MFP is in use. * - * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a - * beacon or probe response from a compatible mesh peer. This is only - * sent while no station information (sta_info) exists for the new peer - * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On - * reception of this notification, userspace may decide to create a new - * station (@NL80211_CMD_NEW_STATION). To stop this notification from - * reoccurring, the userspace authentication daemon may want to create the - * new station with the AUTHENTICATED flag unset and maybe change it later - * depending on the authentication result. - * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -532,8 +522,6 @@ enum nl80211_commands { NL80211_CMD_UNPROT_DEAUTHENTICATE, NL80211_CMD_UNPROT_DISASSOCIATE, - NL80211_CMD_NEW_PEER_CANDIDATE, - /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -557,7 +545,6 @@ enum nl80211_commands { /* source-level API compatibility */ #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG #define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG -#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE /** * enum nl80211_attrs - nl80211 netlink attributes @@ -899,9 +886,6 @@ enum nl80211_commands { * changed once the mesh is active. * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute * containing attributes from &enum nl80211_meshconf_params. - * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver - * allows auth frames in a mesh to be passed to userspace for processing via - * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -1090,8 +1074,6 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, - NL80211_ATTR_SUPPORT_MESH_AUTH, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1186,7 +1168,6 @@ enum nl80211_iftype { * with short barker preamble * @NL80211_STA_FLAG_WME: station is WME/QoS capable * @NL80211_STA_FLAG_MFP: station uses management frame protection - * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated * @NL80211_STA_FLAG_MAX: highest station flag number currently defined * @__NL80211_STA_FLAG_AFTER_LAST: internal use */ @@ -1196,7 +1177,6 @@ enum nl80211_sta_flags { NL80211_STA_FLAG_SHORT_PREAMBLE, NL80211_STA_FLAG_WME, NL80211_STA_FLAG_MFP, - NL80211_STA_FLAG_AUTHENTICATED, /* keep last */ __NL80211_STA_FLAG_AFTER_LAST, @@ -1241,36 +1221,6 @@ enum nl80211_rate_info { NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 }; -/** - * enum nl80211_sta_bss_param - BSS information collected by STA - * - * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM - * when getting information about the bitrate of a station. - * - * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved - * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag) - * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled - * (flag) - * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled - * (flag) - * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8) - * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16) - * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined - * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use - */ -enum nl80211_sta_bss_param { - __NL80211_STA_BSS_PARAM_INVALID, - NL80211_STA_BSS_PARAM_CTS_PROT, - NL80211_STA_BSS_PARAM_SHORT_PREAMBLE, - NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME, - NL80211_STA_BSS_PARAM_DTIM_PERIOD, - NL80211_STA_BSS_PARAM_BEACON_INTERVAL, - - /* keep last */ - __NL80211_STA_BSS_PARAM_AFTER_LAST, - NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1 -}; - /** * enum nl80211_sta_info - station information * @@ -1283,7 +1233,7 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute - * containing info as possible, see &enum nl80211_rate_info + * containing info as possible, see &enum nl80211_sta_info_txrate. * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this * station) @@ -1295,9 +1245,6 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested * attribute, like NL80211_STA_INFO_TX_BITRATE. - * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute - * containing info as possible, see &enum nl80211_sta_bss_param - * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -1317,8 +1264,6 @@ enum nl80211_sta_info { NL80211_STA_INFO_TX_FAILED, NL80211_STA_INFO_SIGNAL_AVG, NL80211_STA_INFO_RX_BITRATE, - NL80211_STA_INFO_BSS_PARAM, - NL80211_STA_INFO_CONNECTED_TIME, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -1741,12 +1686,9 @@ enum nl80211_meshconf_params { * vendor specific path metric or disable it to use the default Airtime * metric. * - * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a - * robust security network ie, or a vendor specific information element that - * vendors will use to identify the path selection methods and metrics in use. - * - * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication - * daemon will be authenticating mesh candidates. + * @NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE: A vendor specific information + * element that vendors will use to identify the path selection methods and + * metrics in use. * * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use @@ -1755,8 +1697,7 @@ enum nl80211_mesh_setup_params { __NL80211_MESH_SETUP_INVALID, NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL, NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, - NL80211_MESH_SETUP_IE, - NL80211_MESH_SETUP_USERSPACE_AUTH, + NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE, /* keep last */ __NL80211_MESH_SETUP_ATTR_AFTER_LAST, diff --git a/trunk/include/linux/rfkill-regulator.h b/trunk/include/linux/rfkill-regulator.h deleted file mode 100644 index aca36bc83315..000000000000 --- a/trunk/include/linux/rfkill-regulator.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * rfkill-regulator.c - Regulator consumer driver for rfkill - * - * Copyright (C) 2009 Guiming Zhuo - * Copyright (C) 2011 Antonio Ospite - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef __LINUX_RFKILL_REGULATOR_H -#define __LINUX_RFKILL_REGULATOR_H - -/* - * Use "vrfkill" as supply id when declaring the regulator consumer: - * - * static struct regulator_consumer_supply pcap_regulator_V6_consumers [] = { - * { .dev_name = "rfkill-regulator.0", .supply = "vrfkill" }, - * }; - * - * If you have several regulator driven rfkill, you can append a numerical id to - * .dev_name as done above, and use the same id when declaring the platform - * device: - * - * static struct rfkill_regulator_platform_data ezx_rfkill_bt_data = { - * .name = "ezx-bluetooth", - * .type = RFKILL_TYPE_BLUETOOTH, - * }; - * - * static struct platform_device a910_rfkill = { - * .name = "rfkill-regulator", - * .id = 0, - * .dev = { - * .platform_data = &ezx_rfkill_bt_data, - * }, - * }; - */ - -#include - -struct rfkill_regulator_platform_data { - char *name; /* the name for the rfkill switch */ - enum rfkill_type type; /* the type as specified in rfkill.h */ -}; - -#endif /* __LINUX_RFKILL_REGULATOR_H */ diff --git a/trunk/include/linux/ssb/ssb.h b/trunk/include/linux/ssb/ssb.h index 7e99b348834c..9659eff52ca2 100644 --- a/trunk/include/linux/ssb/ssb.h +++ b/trunk/include/linux/ssb/ssb.h @@ -308,7 +308,7 @@ struct ssb_bus { /* ID information about the Chip. */ u16 chip_id; - u8 chip_rev; + u16 chip_rev; u16 sprom_offset; u16 sprom_size; /* number of words in sprom */ u8 chip_package; diff --git a/trunk/include/linux/ssb/ssb_driver_chipcommon.h b/trunk/include/linux/ssb/ssb_driver_chipcommon.h index a08d693d8324..2cdf249b4e5f 100644 --- a/trunk/include/linux/ssb/ssb_driver_chipcommon.h +++ b/trunk/include/linux/ssb/ssb_driver_chipcommon.h @@ -123,8 +123,6 @@ #define SSB_CHIPCO_FLASHDATA 0x0048 #define SSB_CHIPCO_BCAST_ADDR 0x0050 #define SSB_CHIPCO_BCAST_DATA 0x0054 -#define SSB_CHIPCO_GPIOPULLUP 0x0058 /* Rev >= 20 only */ -#define SSB_CHIPCO_GPIOPULLDOWN 0x005C /* Rev >= 20 only */ #define SSB_CHIPCO_GPIOIN 0x0060 #define SSB_CHIPCO_GPIOOUT 0x0064 #define SSB_CHIPCO_GPIOOUTEN 0x0068 @@ -133,9 +131,6 @@ #define SSB_CHIPCO_GPIOIRQ 0x0074 #define SSB_CHIPCO_WATCHDOG 0x0080 #define SSB_CHIPCO_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ -#define SSB_CHIPCO_GPIOTIMER_OFFTIME 0x0000FFFF -#define SSB_CHIPCO_GPIOTIMER_OFFTIME_SHIFT 0 -#define SSB_CHIPCO_GPIOTIMER_ONTIME 0xFFFF0000 #define SSB_CHIPCO_GPIOTIMER_ONTIME_SHIFT 16 #define SSB_CHIPCO_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ #define SSB_CHIPCO_CLOCK_N 0x0090 @@ -194,10 +189,8 @@ #define SSB_CHIPCO_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ #define SSB_CHIPCO_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ #define SSB_CHIPCO_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ -#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00010000 /* ALP available */ -#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00020000 /* HT available */ -#define SSB_CHIPCO_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */ -#define SSB_CHIPCO_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */ +#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00010000 /* HT available */ +#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00020000 /* APL available */ #define SSB_CHIPCO_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ #define SSB_CHIPCO_UART0_DATA 0x0300 #define SSB_CHIPCO_UART0_IMR 0x0304 diff --git a/trunk/include/linux/ssb/ssb_regs.h b/trunk/include/linux/ssb/ssb_regs.h index efbf459d571c..402955ae48ce 100644 --- a/trunk/include/linux/ssb/ssb_regs.h +++ b/trunk/include/linux/ssb/ssb_regs.h @@ -97,7 +97,7 @@ #define SSB_INTVEC_ENET1 0x00000040 /* Enable interrupts for enet 1 */ #define SSB_TMSLOW 0x0F98 /* SB Target State Low */ #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ -#define SSB_TMSLOW_REJECT 0x00000002 /* Reject (Standard Backplane) */ +#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ diff --git a/trunk/include/linux/wl12xx.h b/trunk/include/linux/wl12xx.h index 4b697395326e..bebb8efea0a6 100644 --- a/trunk/include/linux/wl12xx.h +++ b/trunk/include/linux/wl12xx.h @@ -24,26 +24,12 @@ #ifndef _LINUX_WL12XX_H #define _LINUX_WL12XX_H -/* Reference clock values */ +/* The board reference clock values */ enum { - WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ - WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ - WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ - WL12XX_REFCLOCK_52 = 3, /* 52 MHz */ - WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */ - WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */ -}; - -/* TCXO clock values */ -enum { - WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */ - WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */ - WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */ - WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */ - WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */ - WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */ - WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */ - WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */ + WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ + WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ + WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ + WL12XX_REFCLOCK_54 = 3, /* 54 MHz */ }; struct wl12xx_platform_data { @@ -52,13 +38,8 @@ struct wl12xx_platform_data { int irq; bool use_eeprom; int board_ref_clock; - int board_tcxo_clock; - unsigned long platform_quirks; }; -/* Platform does not support level trigger interrupts */ -#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0) - #ifdef CONFIG_WL12XX_PLATFORM_DATA int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index d30eada7c6cd..b2b9d28cb4ab 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -422,8 +422,6 @@ struct station_parameters { * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled * @STATION_INFO_SIGNAL_AVG: @signal_avg filled * @STATION_INFO_RX_BITRATE: @rxrate fields are filled - * @STATION_INFO_BSS_PARAM: @bss_param filled - * @STATION_INFO_CONNECTED_TIME: @connected_time filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -441,8 +439,6 @@ enum station_info_flags { STATION_INFO_RX_DROP_MISC = 1<<12, STATION_INFO_SIGNAL_AVG = 1<<13, STATION_INFO_RX_BITRATE = 1<<14, - STATION_INFO_BSS_PARAM = 1<<15, - STATION_INFO_CONNECTED_TIME = 1<<16 }; /** @@ -476,44 +472,12 @@ struct rate_info { u16 legacy; }; -/** - * enum station_info_rate_flags - bitrate info flags - * - * Used by the driver to indicate the specific rate transmission - * type for 802.11n transmissions. - * - * @BSS_PARAM_FLAGS_CTS_PROT: whether CTS protection is enabled - * @BSS_PARAM_FLAGS_SHORT_PREAMBLE: whether short preamble is enabled - * @BSS_PARAM_FLAGS_SHORT_SLOT_TIME: whether short slot time is enabled - */ -enum bss_param_flags { - BSS_PARAM_FLAGS_CTS_PROT = 1<<0, - BSS_PARAM_FLAGS_SHORT_PREAMBLE = 1<<1, - BSS_PARAM_FLAGS_SHORT_SLOT_TIME = 1<<2, -}; - -/** - * struct sta_bss_parameters - BSS parameters for the attached station - * - * Information about the currently associated BSS - * - * @flags: bitflag of flags from &enum bss_param_flags - * @dtim_period: DTIM period for the BSS - * @beacon_interval: beacon interval - */ -struct sta_bss_parameters { - u8 flags; - u8 dtim_period; - u16 beacon_interval; -}; - /** * struct station_info - station information * * Station information filled by driver for get_station() and dump_station. * * @filled: bitflag of flags from &enum station_info_flags - * @connected_time: time(in secs) since a station is last connected * @inactive_time: time since last station activity (tx/rx) in milliseconds * @rx_bytes: bytes received from this station * @tx_bytes: bytes transmitted to this station @@ -536,7 +500,6 @@ struct sta_bss_parameters { */ struct station_info { u32 filled; - u32 connected_time; u32 inactive_time; u32 rx_bytes; u32 tx_bytes; @@ -552,7 +515,6 @@ struct station_info { u32 tx_retries; u32 tx_failed; u32 rx_dropped_misc; - struct sta_bss_parameters bss_param; int generation; }; @@ -693,9 +655,8 @@ struct mesh_config { * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes * @path_sel_proto: which path selection protocol to use * @path_metric: which metric to use - * @ie: vendor information elements (optional) - * @ie_len: length of vendor information elements - * @is_secure: or not + * @vendor_ie: vendor information elements (optional) + * @vendor_ie_len: length of vendor information elements * * These parameters are fixed when the mesh is created. */ @@ -704,9 +665,8 @@ struct mesh_setup { u8 mesh_id_len; u8 path_sel_proto; u8 path_metric; - const u8 *ie; - u8 ie_len; - bool is_secure; + const u8 *vendor_ie; + u8 vendor_ie_len; }; /** @@ -1457,8 +1417,6 @@ struct cfg80211_ops { * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate * unicast and multicast TX keys. - * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing - * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1471,7 +1429,6 @@ enum wiphy_flags { WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), WIPHY_FLAG_IBSS_RSN = BIT(8), WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), - WIPHY_FLAG_MESH_AUTH = BIT(10), }; struct mac_address { @@ -2492,22 +2449,6 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, */ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); -/** - * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate - * - * @dev: network device - * @macaddr: the MAC address of the new candidate - * @ie: information elements advertised by the peer candidate - * @ie_len: lenght of the information elements buffer - * @gfp: allocation flags - * - * This function notifies cfg80211 that the mesh peer candidate has been - * detected, most likely via a beacon or, less likely, via a probe response. - * cfg80211 then sends a notification to userspace. - */ -void cfg80211_notify_new_peer_candidate(struct net_device *dev, - const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp); - /** * DOC: RFkill integration * @@ -2725,15 +2666,6 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev, void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); -/** - * cfg80211_del_sta - notify userspace about deletion of a station - * - * @dev: the netdev - * @mac_addr: the station's address - * @gfp: allocation flags - */ -void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); - /** * cfg80211_rx_mgmt - notification of received, unprocessed management frame * @dev: network device diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 63f75a06043b..965f1b16e53a 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -1819,13 +1819,6 @@ enum ieee80211_ampdu_mlme_action { * @set_ringparam: Set tx and rx ring sizes. * * @get_ringparam: Get tx and rx ring current and maximum sizes. - * - * @tx_frames_pending: Check if there is any pending frame in the hardware - * queues before entering power save. - * - * @set_bitrate_mask: Set a mask of rates to be used for rate control selection - * when transmitting a frame. Currently only legacy rates are handled. - * The callback can sleep. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1913,9 +1906,6 @@ struct ieee80211_ops { int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); void (*get_ringparam)(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); - bool (*tx_frames_pending)(struct ieee80211_hw *hw); - int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - const struct cfg80211_bitrate_mask *mask); }; /** @@ -2232,18 +2222,6 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, */ #define IEEE80211_TX_STATUS_HEADROOM 13 -/** - * ieee80211_sta_set_tim - set the TIM bit for a sleeping station - * - * If a driver buffers frames for a powersave station instead of passing - * them back to mac80211 for retransmission, the station needs to be told - * to wake up using the TIM bitmap in the beacon. - * - * This function sets the station's TIM bit - it will be cleared when the - * station wakes up. - */ -void ieee80211_sta_set_tim(struct ieee80211_sta *sta); - /** * ieee80211_tx_status - transmit status callback * @@ -2297,17 +2275,6 @@ static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw, void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); -/** - * ieee80211_report_low_ack - report non-responding station - * - * When operating in AP-mode, call this function to report a non-responding - * connected STA. - * - * @sta: the non-responding connected sta - * @num_packets: number of packets sent to @sta without a response - */ -void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); - /** * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index 227bde39ee58..98aa24b92c58 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -586,6 +586,9 @@ static int hci_dev_do_close(struct hci_dev *hdev) hci_req_cancel(hdev, ENODEV); hci_req_lock(hdev); + /* Stop timer, it might be running */ + del_timer_sync(&hdev->cmd_timer); + if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { del_timer_sync(&hdev->cmd_timer); hci_req_unlock(hdev); @@ -626,7 +629,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) /* Drop last sent command */ if (hdev->sent_cmd) { - del_timer_sync(&hdev->cmd_timer); kfree_skb(hdev->sent_cmd); hdev->sent_cmd = NULL; } diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index f5fdfcbf552a..513f85cc2ae1 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -2,6 +2,7 @@ config MAC80211 tristate "Generic IEEE 802.11 Networking Stack (mac80211)" depends on CFG80211 select CRYPTO + select CRYPTO_ECB select CRYPTO_ARC4 select CRYPTO_AES select CRC32 diff --git a/trunk/net/mac80211/aes_ccm.c b/trunk/net/mac80211/aes_ccm.c index b9b595c08112..4bd6ef0be380 100644 --- a/trunk/net/mac80211/aes_ccm.c +++ b/trunk/net/mac80211/aes_ccm.c @@ -54,12 +54,13 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, u8 *cdata, u8 *mic) { int i, j, last_len, num_blocks; - u8 *pos, *cpos, *b, *s_0, *e, *b_0; + u8 *pos, *cpos, *b, *s_0, *e, *b_0, *aad; b = scratch; s_0 = scratch + AES_BLOCK_LEN; e = scratch + 2 * AES_BLOCK_LEN; b_0 = scratch + 3 * AES_BLOCK_LEN; + aad = scratch + 4 * AES_BLOCK_LEN; num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; @@ -93,12 +94,13 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, u8 *cdata, size_t data_len, u8 *mic, u8 *data) { int i, j, last_len, num_blocks; - u8 *pos, *cpos, *b, *s_0, *a, *b_0; + u8 *pos, *cpos, *b, *s_0, *a, *b_0, *aad; b = scratch; s_0 = scratch + AES_BLOCK_LEN; a = scratch + 2 * AES_BLOCK_LEN; b_0 = scratch + 3 * AES_BLOCK_LEN; + aad = scratch + 4 * AES_BLOCK_LEN; num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 12d52cec9515..44049733c4ea 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -330,7 +330,6 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = sta->sdata; - struct timespec uptime; sinfo->generation = sdata->local->sta_generation; @@ -343,12 +342,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) STATION_INFO_TX_FAILED | STATION_INFO_TX_BITRATE | STATION_INFO_RX_BITRATE | - STATION_INFO_RX_DROP_MISC | - STATION_INFO_BSS_PARAM | - STATION_INFO_CONNECTED_TIME; - - do_posix_clock_monotonic_gettime(&uptime); - sinfo->connected_time = uptime.tv_sec - sta->last_connected; + STATION_INFO_RX_DROP_MISC; sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); sinfo->rx_bytes = sta->rx_bytes; @@ -395,16 +389,6 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->plink_state = sta->plink_state; #endif } - - sinfo->bss_param.flags = 0; - if (sdata->vif.bss_conf.use_cts_prot) - sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; - if (sdata->vif.bss_conf.use_short_preamble) - sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; - if (sdata->vif.bss_conf.use_short_slot) - sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; - sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; - sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; } @@ -691,12 +675,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, if (set & BIT(NL80211_STA_FLAG_MFP)) sta->flags |= WLAN_STA_MFP; } - - if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { - sta->flags &= ~WLAN_STA_AUTH; - if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) - sta->flags |= WLAN_STA_AUTH; - } spin_unlock_irqrestore(&sta->flaglock, flags); /* @@ -1045,26 +1023,26 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, u8 *new_ie; const u8 *old_ie; - /* allocate information elements */ + /* first allocate the new vendor information element */ new_ie = NULL; - old_ie = ifmsh->ie; + old_ie = ifmsh->vendor_ie; - if (setup->ie_len) { - new_ie = kmemdup(setup->ie, setup->ie_len, + ifmsh->vendor_ie_len = setup->vendor_ie_len; + if (setup->vendor_ie_len) { + new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, GFP_KERNEL); if (!new_ie) return -ENOMEM; } - ifmsh->ie_len = setup->ie_len; - ifmsh->ie = new_ie; - kfree(old_ie); /* now copy the rest of the setup parameters */ ifmsh->mesh_id_len = setup->mesh_id_len; memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; - ifmsh->is_secure = setup->is_secure; + ifmsh->vendor_ie = new_ie; + + kfree(old_ie); return 0; } @@ -1633,13 +1611,16 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - int i, ret; + int i; + + /* + * This _could_ be supported by providing a hook for + * drivers for this function, but at this point it + * doesn't seem worth bothering. + */ + if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) + return -EOPNOTSUPP; - if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { - ret = drv_set_bitrate_mask(local, sdata, mask); - if (ret) - return ret; - } for (i = 0; i < IEEE80211_NUM_BANDS; i++) sdata->rc_rateidx_mask[i] = mask->control[i].legacy; diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 0a602dbfdb2b..51f0d780dafa 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -37,7 +37,7 @@ int mac80211_format_buffer(char __user *userbuf, size_t count, return simple_read_from_buffer(userbuf, count, ppos, buf, res); } -#define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \ +#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ static ssize_t name## _read(struct file *file, char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ @@ -45,19 +45,14 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ \ return mac80211_format_buffer(userbuf, count, ppos, \ fmt "\n", ##value); \ -} - -#define DEBUGFS_READONLY_FILE_OPS(name) \ +} \ + \ static const struct file_operations name## _ops = { \ .read = name## _read, \ .open = mac80211_open_file_generic, \ .llseek = generic_file_llseek, \ }; -#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ - DEBUGFS_READONLY_FILE_FN(name, fmt, value) \ - DEBUGFS_READONLY_FILE_OPS(name) - #define DEBUGFS_ADD(name) \ debugfs_create_file(#name, 0400, phyd, local, &name## _ops); @@ -296,70 +291,11 @@ static ssize_t channel_type_read(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); } -static ssize_t hwflags_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_local *local = file->private_data; - int mxln = 500; - ssize_t rv; - char *buf = kzalloc(mxln, GFP_KERNEL); - int sf = 0; /* how many written so far */ - - sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); - if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) - sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); - if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) - sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); - if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) - sf += snprintf(buf + sf, mxln - sf, - "HOST_BCAST_PS_BUFFERING\n"); - if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) - sf += snprintf(buf + sf, mxln - sf, - "2GHZ_SHORT_SLOT_INCAPABLE\n"); - if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) - sf += snprintf(buf + sf, mxln - sf, - "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); - if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) - sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); - if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) - sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); - if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) - sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); - if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) - sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); - if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) - sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); - if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) - sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); - if (local->hw.flags & IEEE80211_HW_BEACON_FILTER) - sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); - if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) - sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n"); - if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); - if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) - sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); - - rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); - kfree(buf); - return rv; -} +static const struct file_operations channel_type_ops = { + .read = channel_type_read, + .open = mac80211_open_file_generic, + .llseek = default_llseek, +}; static ssize_t queues_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -379,9 +315,11 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, buf, res); } -DEBUGFS_READONLY_FILE_OPS(hwflags); -DEBUGFS_READONLY_FILE_OPS(channel_type); -DEBUGFS_READONLY_FILE_OPS(queues); +static const struct file_operations queues_ops = { + .read = queues_read, + .open = mac80211_open_file_generic, + .llseek = default_llseek, +}; /* statistics stuff */ @@ -457,7 +395,6 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(uapsd_queues); DEBUGFS_ADD(uapsd_max_sp_len); DEBUGFS_ADD(channel_type); - DEBUGFS_ADD(hwflags); DEBUGFS_ADD(user_power); DEBUGFS_ADD(power); diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index a01d2137fddc..c04a1396cf8d 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -92,31 +92,6 @@ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf, } STA_OPS(inactive_ms); - -static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct sta_info *sta = file->private_data; - struct timespec uptime; - struct tm result; - long connected_time_secs; - char buf[100]; - int res; - do_posix_clock_monotonic_gettime(&uptime); - connected_time_secs = uptime.tv_sec - sta->last_connected; - time_to_tm(connected_time_secs, 0, &result); - result.tm_year -= 70; - result.tm_mday -= 1; - res = scnprintf(buf, sizeof(buf), - "years - %ld\nmonths - %d\ndays - %d\nclock - %d:%d:%d\n\n", - result.tm_year, result.tm_mon, result.tm_mday, - result.tm_hour, result.tm_min, result.tm_sec); - return simple_read_from_buffer(userbuf, count, ppos, buf, res); -} -STA_OPS(connected_time); - - - static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -349,7 +324,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD(flags); DEBUGFS_ADD(num_ps_buf_frames); DEBUGFS_ADD(inactive_ms); - DEBUGFS_ADD(connected_time); DEBUGFS_ADD(last_seq_ctrl); DEBUGFS_ADD(agg_status); DEBUGFS_ADD(dev); diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index 2ddb56e5b51f..9c0d62bb0ea3 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -552,35 +552,4 @@ static inline void drv_get_ringparam(struct ieee80211_local *local, trace_drv_return_void(local); } -static inline bool drv_tx_frames_pending(struct ieee80211_local *local) -{ - bool ret = false; - - might_sleep(); - - trace_drv_tx_frames_pending(local); - if (local->ops->tx_frames_pending) - ret = local->ops->tx_frames_pending(&local->hw); - trace_drv_return_bool(local, ret); - - return ret; -} - -static inline int drv_set_bitrate_mask(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - const struct cfg80211_bitrate_mask *mask) -{ - int ret = -EOPNOTSUPP; - - might_sleep(); - - trace_drv_set_bitrate_mask(local, sdata, mask); - if (local->ops->set_bitrate_mask) - ret = local->ops->set_bitrate_mask(&local->hw, - &sdata->vif, mask); - trace_drv_return_int(local, ret); - - return ret; -} - #endif /* __MAC80211_DRIVER_OPS */ diff --git a/trunk/net/mac80211/driver-trace.h b/trunk/net/mac80211/driver-trace.h index 191e834ec46b..45aab80738e2 100644 --- a/trunk/net/mac80211/driver-trace.h +++ b/trunk/net/mac80211/driver-trace.h @@ -74,21 +74,6 @@ TRACE_EVENT(drv_return_int, TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret) ); -TRACE_EVENT(drv_return_bool, - TP_PROTO(struct ieee80211_local *local, bool ret), - TP_ARGS(local, ret), - TP_STRUCT__entry( - LOCAL_ENTRY - __field(bool, ret) - ), - TP_fast_assign( - LOCAL_ASSIGN; - __entry->ret = ret; - ), - TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ? - "true" : "false") -); - TRACE_EVENT(drv_return_u64, TP_PROTO(struct ieee80211_local *local, u64 ret), TP_ARGS(local, ret), @@ -979,43 +964,11 @@ TRACE_EVENT(drv_get_ringparam, ) ); -DEFINE_EVENT(local_only_evt, drv_tx_frames_pending, - TP_PROTO(struct ieee80211_local *local), - TP_ARGS(local) -); - DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) ); -TRACE_EVENT(drv_set_bitrate_mask, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - const struct cfg80211_bitrate_mask *mask), - - TP_ARGS(local, sdata, mask), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - __field(u32, legacy_2g) - __field(u32, legacy_5g) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - __entry->legacy_2g = mask->control[IEEE80211_BAND_2GHZ].legacy; - __entry->legacy_5g = mask->control[IEEE80211_BAND_5GHZ].legacy; - ), - - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " 2G Mask:0x%x 5G Mask:0x%x", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->legacy_2g, __entry->legacy_5g - ) -); - /* * Tracing for API calls that drivers call. */ diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index b81860c94698..3e81af1fce58 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -40,7 +40,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - u16 auth_alg, auth_transaction; + u16 auth_alg, auth_transaction, status_code; lockdep_assert_held(&sdata->u.ibss.mtx); @@ -49,6 +49,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + status_code = le16_to_cpu(mgmt->u.auth.status_code); /* * IEEE 802.11 standard does not require authentication in IBSS @@ -526,6 +527,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN]; u16 capability; int i; @@ -548,6 +551,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", sdata->name, bssid); + sband = local->hw.wiphy->bands[ifibss->channel->band]; + capability = WLAN_CAPABILITY_IBSS; if (ifibss->privacy) @@ -656,6 +661,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct sk_buff *req) { + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req); struct ieee80211_mgmt *mgmt = (void *)req->data; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; @@ -679,7 +685,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, mgmt->bssid, tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) + if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH)) return; if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 9e3b4f0f31bd..a40401701424 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -488,9 +488,8 @@ struct ieee80211_if_mesh { struct mesh_config mshcfg; u32 mesh_seqnum; bool accepting_plinks; - const u8 *ie; - u8 ie_len; - bool is_secure; + const u8 *vendor_ie; + u8 vendor_ie_len; }; #ifdef CONFIG_MAC80211_MESH @@ -766,9 +765,6 @@ struct ieee80211_local { int tx_headroom; /* required headroom for hardware/radiotap */ - /* count for keys needing tailroom space allocation */ - int crypto_tx_tailroom_needed_cnt; - /* Tasklet and skb queue to process calls from IRQ mode. All frames * added to skb_queue will be processed, but frames in * skb_queue_unreliable may be dropped if the total length of these @@ -813,8 +809,8 @@ struct ieee80211_local { struct rate_control_ref *rate_ctrl; - struct crypto_cipher *wep_tx_tfm; - struct crypto_cipher *wep_rx_tfm; + struct crypto_blkcipher *wep_tx_tfm; + struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; /* see iface.c */ diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index ca3c626b011a..af3c56482c80 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -101,10 +101,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; - - if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) - key->local->crypto_tx_tailroom_needed_cnt--; - return 0; } @@ -160,9 +156,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; - - if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) - key->local->crypto_tx_tailroom_needed_cnt++; } void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) @@ -395,10 +388,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) ieee80211_aes_key_free(key->u.ccmp.tfm); if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); - if (key->local) { + if (key->local) ieee80211_debugfs_key_remove(key); - key->local->crypto_tx_tailroom_needed_cnt--; - } kfree(key); } @@ -460,8 +451,6 @@ int ieee80211_key_link(struct ieee80211_key *key, ieee80211_debugfs_key_add(key); - key->local->crypto_tx_tailroom_needed_cnt++; - ret = ieee80211_key_enable_hw_accel(key); mutex_unlock(&sdata->local->key_mtx); @@ -503,12 +492,8 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->local->key_mtx); - sdata->local->crypto_tx_tailroom_needed_cnt = 0; - - list_for_each_entry(key, &sdata->key_list, list) { - sdata->local->crypto_tx_tailroom_needed_cnt++; + list_for_each_entry(key, &sdata->key_list, list) ieee80211_key_enable_hw_accel(key); - } mutex_unlock(&sdata->local->key_mtx); } diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index 61877662e8f8..562d2984c482 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -33,6 +33,12 @@ #include "cfg.h" #include "debugfs.h" + +static bool ieee80211_disable_40mhz_24ghz; +module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); +MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, + "Disable 40MHz support in the 2.4GHz band"); + static struct lock_class_key ieee80211_rx_skb_queue_class; void ieee80211_configure_filter(struct ieee80211_local *local) @@ -539,9 +545,7 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, [NL80211_IFTYPE_MESH_POINT] = { .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4), }, }; @@ -722,6 +726,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } channels += sband->n_channels; + /* + * Since ieee80211_disable_40mhz_24ghz is global, we can + * modify the sband's ht data even if the driver uses a + * global structure for that. + */ + if (ieee80211_disable_40mhz_24ghz && + band == IEEE80211_BAND_2GHZ && + sband->ht_cap.ht_supported) { + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } + if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; @@ -744,11 +760,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); #endif - /* if the underlying driver supports mesh, mac80211 will (at least) - * provide routing of mesh authentication frames to userspace */ - if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT)) - local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH; - /* mac80211 supports control port protocol changing */ local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; @@ -868,6 +879,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->dynamic_ps_forced_timeout = -1; + result = sta_info_start(local); + if (result < 0) + goto fail_sta_info; + result = ieee80211_wep_init(local); if (result < 0) wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", @@ -930,6 +945,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) rtnl_unlock(); ieee80211_wep_free(local); sta_info_stop(local); + fail_sta_info: destroy_workqueue(local->workqueue); fail_workqueue: wiphy_unregister(local->hw.wiphy); diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index c1299e249541..2a57cc02c618 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -279,9 +279,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; *pos++ = 0x00; - if (sdata->u.mesh.ie) { - int len = sdata->u.mesh.ie_len; - const u8 *data = sdata->u.mesh.ie; + if (sdata->u.mesh.vendor_ie) { + int len = sdata->u.mesh.vendor_ie_len; + const u8 *data = sdata->u.mesh.vendor_ie; if (skb_tailroom(skb) > len) memcpy(skb_put(skb, len), data, len); } @@ -573,10 +573,6 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); - /* ignore beacons from secure mesh peers if our security is off */ - if (elems.rsn_len && !sdata->u.mesh.is_secure) - return; - if (elems.ds_params && elems.ds_params_len == 1) freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); else @@ -590,7 +586,9 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (elems.mesh_id && elems.mesh_config && mesh_matches_local(&elems, sdata)) { supp_rates = ieee80211_sta_get_rates(local, &elems, band); - mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); + + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, + mesh_peer_accepts_plinks(&elems)); } } @@ -613,9 +611,12 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_rx_status *rx_status; + struct ieee80211_if_mesh *ifmsh; struct ieee80211_mgmt *mgmt; u16 stype; + ifmsh = &sdata->u.mesh; + rx_status = IEEE80211_SKB_RXCB(skb); mgmt = (struct ieee80211_mgmt *) skb->data; stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 10acf1cc8082..b99e230fe31c 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -226,8 +226,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ void mesh_neighbour_update(u8 *hw_addr, u32 rates, - struct ieee80211_sub_if_data *sdata, - struct ieee802_11_elems *ie); + struct ieee80211_sub_if_data *sdata, bool add); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index e57f2e728cfe..5bf64d7112b3 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -633,6 +633,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, struct mesh_path *mpath; u8 ttl; u8 *ta, *target_addr; + u8 target_flags; u32 target_sn; u16 target_rcode; @@ -643,6 +644,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, return; } ttl--; + target_flags = PERR_IE_TARGET_FLAGS(perr_elem); target_addr = PERR_IE_TARGET_ADDR(perr_elem); target_sn = PERR_IE_TARGET_SN(perr_elem); target_rcode = PERR_IE_TARGET_RCODE(perr_elem); @@ -673,10 +675,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_path *mpath; + u8 *ta; u8 ttl, flags, hopcount; u8 *orig_addr; u32 orig_sn, metric; + ta = mgmt->sa; ttl = rann->rann_ttl; if (ttl <= 1) { ifmsh->mshstats.dropped_frames_ttl++; diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index 7776ae5a8f15..8d65b47d9837 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -65,37 +65,42 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) __mesh_table_free(tbl); } -static int mesh_table_grow(struct mesh_table *oldtbl, - struct mesh_table *newtbl) +static struct mesh_table *mesh_table_grow(struct mesh_table *tbl) { + struct mesh_table *newtbl; struct hlist_head *oldhash; struct hlist_node *p, *q; int i; - if (atomic_read(&oldtbl->entries) - < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) - return -EAGAIN; + if (atomic_read(&tbl->entries) + < tbl->mean_chain_len * (tbl->hash_mask + 1)) + goto endgrow; + newtbl = mesh_table_alloc(tbl->size_order + 1); + if (!newtbl) + goto endgrow; - newtbl->free_node = oldtbl->free_node; - newtbl->mean_chain_len = oldtbl->mean_chain_len; - newtbl->copy_node = oldtbl->copy_node; - atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); + newtbl->free_node = tbl->free_node; + newtbl->mean_chain_len = tbl->mean_chain_len; + newtbl->copy_node = tbl->copy_node; + atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); - oldhash = oldtbl->hash_buckets; - for (i = 0; i <= oldtbl->hash_mask; i++) + oldhash = tbl->hash_buckets; + for (i = 0; i <= tbl->hash_mask; i++) hlist_for_each(p, &oldhash[i]) - if (oldtbl->copy_node(p, newtbl) < 0) + if (tbl->copy_node(p, newtbl) < 0) goto errcopy; - return 0; + return newtbl; errcopy: for (i = 0; i <= newtbl->hash_mask; i++) { hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) - oldtbl->free_node(p, 0); + tbl->free_node(p, 0); } - return -ENOMEM; + __mesh_table_free(newtbl); +endgrow: + return NULL; } @@ -329,13 +334,10 @@ void mesh_mpath_table_grow(void) { struct mesh_table *oldtbl, *newtbl; - newtbl = mesh_table_alloc(mesh_paths->size_order + 1); - if (!newtbl) - return; write_lock(&pathtbl_resize_lock); oldtbl = mesh_paths; - if (mesh_table_grow(mesh_paths, newtbl) < 0) { - __mesh_table_free(newtbl); + newtbl = mesh_table_grow(mesh_paths); + if (!newtbl) { write_unlock(&pathtbl_resize_lock); return; } @@ -350,13 +352,10 @@ void mesh_mpp_table_grow(void) { struct mesh_table *oldtbl, *newtbl; - newtbl = mesh_table_alloc(mpp_paths->size_order + 1); - if (!newtbl) - return; write_lock(&pathtbl_resize_lock); oldtbl = mpp_paths; - if (mesh_table_grow(mpp_paths, newtbl) < 0) { - __mesh_table_free(newtbl); + newtbl = mesh_table_grow(mpp_paths); + if (!newtbl) { write_unlock(&pathtbl_resize_lock); return; } diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index 84e5b056af02..44b53931ba5e 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, if (!sta) return NULL; - sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH; + sta->flags = WLAN_STA_AUTHORIZED; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; rate_control_rate_init(sta); @@ -161,7 +161,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, __le16 reason) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + - sdata->u.mesh.ie_len); + sdata->u.mesh.vendor_ie_len); struct ieee80211_mgmt *mgmt; bool include_plid = false; static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; @@ -237,9 +237,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, return 0; } -void mesh_neighbour_update(u8 *hw_addr, u32 rates, - struct ieee80211_sub_if_data *sdata, - struct ieee802_11_elems *elems) +void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, + bool peer_accepting_plinks) { struct ieee80211_local *local = sdata->local; struct sta_info *sta; @@ -249,14 +248,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, sta = sta_info_get(sdata, hw_addr); if (!sta) { rcu_read_unlock(); - /* Userspace handles peer allocation when security is enabled - * */ - if (sdata->u.mesh.is_secure) - cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, - elems->ie_start, elems->total_len, - GFP_KERNEL); - else - sta = mesh_plink_alloc(sdata, hw_addr, rates); + + sta = mesh_plink_alloc(sdata, hw_addr, rates); if (!sta) return; if (sta_info_insert_rcu(sta)) { @@ -267,8 +260,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, sta->last_rx = jiffies; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; - if (mesh_peer_accepts_plinks(elems) && - sta->plink_state == PLINK_LISTEN && + if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && sdata->u.mesh.accepting_plinks && sdata->u.mesh.mshcfg.auto_open_plinks) mesh_plink_open(sta); @@ -380,9 +372,6 @@ int mesh_plink_open(struct sta_info *sta) __le16 llid; struct ieee80211_sub_if_data *sdata = sta->sdata; - if (!test_sta_flags(sta, WLAN_STA_AUTH)) - return -EPERM; - spin_lock_bh(&sta->lock); get_random_bytes(&llid, 2); sta->llid = llid; @@ -460,10 +449,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mpl_dbg("Mesh plink: missing necessary peer link ie\n"); return; } - if (elems.rsn_len && !sdata->u.mesh.is_secure) { - mpl_dbg("Mesh plink: can't establish link with secure peer\n"); - return; - } ftype = mgmt->u.action.u.plink_action.action_code; ie_len = elems.peer_link_len; @@ -495,12 +480,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { - mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); - rcu_read_unlock(); - return; - } - if (sta && sta->plink_state == PLINK_BLOCKED) { rcu_read_unlock(); return; diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index a41f234bd486..64d92d5a7f40 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -90,11 +90,20 @@ enum rx_mgmt_action { /* no action required */ RX_MGMT_NONE, + /* caller must call cfg80211_send_rx_auth() */ + RX_MGMT_CFG80211_AUTH, + + /* caller must call cfg80211_send_rx_assoc() */ + RX_MGMT_CFG80211_ASSOC, + /* caller must call cfg80211_send_deauth() */ RX_MGMT_CFG80211_DEAUTH, /* caller must call cfg80211_send_disassoc() */ RX_MGMT_CFG80211_DISASSOC, + + /* caller must tell cfg80211 about internal error */ + RX_MGMT_CFG80211_ASSOC_ERROR, }; /* utils */ @@ -761,16 +770,15 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { netif_tx_stop_all_queues(sdata->dev); + /* + * Flush all the frames queued in the driver before + * going to power save + */ + drv_flush(local, false); + ieee80211_send_nullfunc(local, sdata, 1); - if (drv_tx_frames_pending(local)) - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies( - local->hw.conf.dynamic_ps_timeout)); - else { - ieee80211_send_nullfunc(local, sdata, 1); - /* Flush to get the tx status of nullfunc frame */ - drv_flush(local, false); - } + /* Flush once again to get the tx status of nullfunc frame */ + drv_flush(local, false); } if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index 042461710880..e37355193ed1 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -14,23 +14,12 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) ieee80211_scan_cancel(local); - if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { - mutex_lock(&local->sta_mtx); - list_for_each_entry(sta, &local->sta_list, list) { - set_sta_flags(sta, WLAN_STA_BLOCK_BA); - ieee80211_sta_tear_down_BA_sessions(sta, true); - } - mutex_unlock(&local->sta_mtx); - } - ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); /* flush out all packets */ synchronize_net(); - drv_flush(local, false); - local->quiescing = true; /* make quiescing visible to timers everywhere */ mb(); @@ -54,6 +43,11 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) /* tear down aggregation sessions and remove STAs */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + set_sta_flags(sta, WLAN_STA_BLOCK_BA); + ieee80211_sta_tear_down_BA_sessions(sta, true); + } + if (sta->uploaded) { sdata = sta->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index b04a4378adcc..2afeac9c6453 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -143,8 +143,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, if (status->flag & RX_FLAG_HT) { /* * MCS information is a separate field in radiotap, - * added below. The byte here is needed as padding - * for the channel though, so initialise it to 0. + * added below. */ *pos = 0; } else { @@ -503,8 +502,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_probe_req(hdr->frame_control) || ieee80211_is_probe_resp(hdr->frame_control) || - ieee80211_is_beacon(hdr->frame_control) || - ieee80211_is_auth(hdr->frame_control)) + ieee80211_is_beacon(hdr->frame_control)) return RX_CONTINUE; return RX_DROP_MONITOR; @@ -652,7 +650,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, set_release_timer: mod_timer(&tid_agg_rx->reorder_timer, - tid_agg_rx->reorder_time[j] + 1 + + tid_agg_rx->reorder_time[j] + HT_RX_REORDER_BUF_TIMEOUT); } else { del_timer(&tid_agg_rx->reorder_timer); @@ -709,8 +707,6 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, /* * If the current MPDU is in the right order and nothing else * is stored we can process it directly, no need to buffer it. - * If it is first but there's something stored, we may be able - * to release frames after this one. */ if (mpdu_seq_num == tid_agg_rx->head_seq_num && tid_agg_rx->stored_mpdu_num == 0) { @@ -1587,7 +1583,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) } static int -__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) +__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; @@ -1595,7 +1591,6 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) struct ethhdr *ehdr; int ret; - *port_control = false; if (ieee80211_has_a4(hdr->frame_control) && sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) return -1; @@ -1614,13 +1609,11 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) return -1; ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); - if (ret < 0) + if (ret < 0 || !check_port_control) return ret; ehdr = (struct ethhdr *) rx->skb->data; - if (ehdr->h_proto == rx->sdata->control_port_protocol) - *port_control = true; - else if (check_port_control) + if (ehdr->h_proto != rx->sdata->control_port_protocol) return -1; return 0; @@ -1921,7 +1914,6 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) struct net_device *dev = sdata->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; __le16 fc = hdr->frame_control; - bool port_control; int err; if (unlikely(!ieee80211_is_data(hdr->frame_control))) @@ -1938,21 +1930,13 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) sdata->vif.type == NL80211_IFTYPE_AP) return RX_DROP_MONITOR; - err = __ieee80211_data_to_8023(rx, &port_control); + err = __ieee80211_data_to_8023(rx); if (unlikely(err)) return RX_DROP_UNUSABLE; if (!ieee80211_frame_allowed(rx, fc)) return RX_DROP_MONITOR; - if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && - unlikely(port_control) && sdata->bss) { - sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, - u.ap); - dev = sdata->dev; - rx->sdata = sdata; - } - rx->skb->dev = dev; dev->stats.rx_packets++; diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index f05244dc773e..d0311a322ddd 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -228,7 +228,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct sta_info *sta; - struct timespec uptime; int i; sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); @@ -246,8 +245,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->sdata = sdata; sta->last_rx = jiffies; - do_posix_clock_monotonic_gettime(&uptime); - sta->last_connected = uptime.tv_sec; ewma_init(&sta->avg_signal, 1024, 8); if (sta_prepare_rate_control(local, sta, gfp)) { @@ -587,6 +584,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, { unsigned long flags; struct sk_buff *skb; + struct ieee80211_sub_if_data *sdata; if (skb_queue_empty(&sta->ps_tx_buf)) return false; @@ -603,6 +601,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, if (!skb) break; + sdata = sta->sdata; local->total_ps_buffered--; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n", @@ -610,8 +609,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, #endif dev_kfree_skb(skb); - if (skb_queue_empty(&sta->ps_tx_buf) && - !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF)) + if (skb_queue_empty(&sta->ps_tx_buf)) sta_info_clear_tim_bit(sta); } @@ -700,8 +698,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ cancel_work_sync(&sta->drv_unblock_wk); - cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); - rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta); @@ -770,8 +766,9 @@ static void sta_info_cleanup(unsigned long data) if (!timer_needed) return; - mod_timer(&local->sta_cleanup, - round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL)); + local->sta_cleanup.expires = + round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); + add_timer(&local->sta_cleanup); } void sta_info_init(struct ieee80211_local *local) @@ -784,6 +781,14 @@ void sta_info_init(struct ieee80211_local *local) setup_timer(&local->sta_cleanup, sta_info_cleanup, (unsigned long)local); + local->sta_cleanup.expires = + round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); +} + +int sta_info_start(struct ieee80211_local *local) +{ + add_timer(&local->sta_cleanup); + return 0; } void sta_info_stop(struct ieee80211_local *local) @@ -895,7 +900,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; int sent, buffered; - clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); @@ -988,12 +992,3 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, ieee80211_queue_work(hw, &sta->drv_unblock_wk); } EXPORT_SYMBOL(ieee80211_sta_block_awake); - -void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) -{ - struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - - set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); - sta_info_set_tim_bit(sta); -} -EXPORT_SYMBOL(ieee80211_sta_set_tim); diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index af1a7f8c8675..57681149e37f 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -43,8 +43,6 @@ * be in the queues * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping * station in power-save mode, reply when the driver unblocks. - * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal - * buffers. Automatically cleared on station wake-up. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH = 1<<0, @@ -60,7 +58,6 @@ enum ieee80211_sta_info_flags { WLAN_STA_BLOCK_BA = 1<<11, WLAN_STA_PS_DRIVER = 1<<12, WLAN_STA_PSPOLL = 1<<13, - WLAN_STA_PS_DRIVER_BUF = 1<<14, }; #define STA_TID_NUM 16 @@ -229,7 +226,6 @@ enum plink_state { * @rx_bytes: Number of bytes received from this STA * @wep_weak_iv_count: number of weak WEP IVs received from this station * @last_rx: time (in jiffies) when last frame was received from this STA - * @last_connected: time (in seconds) when a station got connected * @num_duplicates: number of duplicate frames received from this STA * @rx_fragments: number of received MPDUs * @rx_dropped: number of dropped MPDUs from this STA @@ -299,7 +295,6 @@ struct sta_info { unsigned long rx_packets, rx_bytes; unsigned long wep_weak_iv_count; unsigned long last_rx; - long last_connected; unsigned long num_duplicates; unsigned long rx_fragments; unsigned long rx_dropped; @@ -502,6 +497,7 @@ void sta_info_set_tim_bit(struct sta_info *sta); void sta_info_clear_tim_bit(struct sta_info *sta); void sta_info_init(struct ieee80211_local *local); +int sta_info_start(struct ieee80211_local *local); void sta_info_stop(struct ieee80211_local *local); int sta_info_flush(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 1658efaa2e8e..b936dd29e92b 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -189,19 +189,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) bool acked; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (info->status.rates[i].idx < 0) { - break; - } else if (i >= hw->max_report_rates) { - /* the HW cannot have attempted that rate */ + /* the HW cannot have attempted that rate */ + if (i >= hw->max_report_rates) { info->status.rates[i].idx = -1; info->status.rates[i].count = 0; - break; + } else if (info->status.rates[i].idx >= 0) { + rates_idx = i; } retry_count += info->status.rates[i].count; } - rates_idx = i - 1; - if (retry_count < 0) retry_count = 0; @@ -446,11 +443,3 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb(skb); } EXPORT_SYMBOL(ieee80211_tx_status); - -void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) -{ - struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, - num_packets, GFP_ATOMIC); -} -EXPORT_SYMBOL(ieee80211_report_low_ack); diff --git a/trunk/net/mac80211/tkip.c b/trunk/net/mac80211/tkip.c index 757e4eb2baf7..e840c9cd46db 100644 --- a/trunk/net/mac80211/tkip.c +++ b/trunk/net/mac80211/tkip.c @@ -202,7 +202,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key); * @payload_len is the length of payload (_not_ including IV/ICV length). * @ta is the transmitter addresses. */ -int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *pos, size_t payload_len, u8 *ta) { @@ -223,7 +223,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, * beginning of the buffer containing IEEE 802.11 header payload, i.e., * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the * length of payload, including IV, Ext. IV, MIC, ICV. */ -int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, diff --git a/trunk/net/mac80211/tkip.h b/trunk/net/mac80211/tkip.h index 1cab9c86978f..7e83dee976fa 100644 --- a/trunk/net/mac80211/tkip.h +++ b/trunk/net/mac80211/tkip.h @@ -15,7 +15,7 @@ u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); -int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *pos, size_t payload_len, u8 *ta); enum { @@ -24,7 +24,7 @@ enum { TKIP_DECRYPT_INVALID_KEYIDX = -2, TKIP_DECRYPT_REPLAY = -3, }; -int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index e3e3aa173af0..ce4596ed1268 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1036,11 +1036,14 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, struct ieee80211_radiotap_iterator iterator; struct ieee80211_radiotap_header *rthdr = (struct ieee80211_radiotap_header *) skb->data; + struct ieee80211_supported_band *sband; bool hw_frag; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, NULL); + sband = tx->local->hw.wiphy->bands[tx->channel->band]; + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; tx->flags &= ~IEEE80211_TX_FRAGMENTED; @@ -1439,8 +1442,11 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, struct ieee80211_tx_data tx; ieee80211_tx_result res_prepare; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u16 queue; bool result = true; + queue = skb_get_queue_mapping(skb); + if (unlikely(skb->len < 10)) { dev_kfree_skb(skb); return true; @@ -1476,7 +1482,12 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, { int tail_need = 0; - if (may_encrypt && local->crypto_tx_tailroom_needed_cnt) { + /* + * This could be optimised, devices that do full hardware + * crypto (including TKIP MMIC) need no tailroom... But we + * have no drivers for such devices currently. + */ + if (may_encrypt) { tail_need = IEEE80211_ENCRYPT_TAILROOM; tail_need -= skb_tailroom(skb); tail_need = max_t(int, tail_need, 0); @@ -2251,7 +2262,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, /* headroom, head length, tail length and maximum TIM length */ skb = dev_alloc_skb(local->tx_headroom + 400 + - sdata->u.mesh.ie_len); + sdata->u.mesh.vendor_ie_len); if (!skb) goto out; @@ -2474,6 +2485,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, { struct ieee80211_local *local = hw_to_local(hw); struct sk_buff *skb = NULL; + struct sta_info *sta; struct ieee80211_tx_data tx; struct ieee80211_sub_if_data *sdata; struct ieee80211_if_ap *bss = NULL; @@ -2515,6 +2527,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, info = IEEE80211_SKB_CB(skb); + sta = tx.sta; tx.flags |= IEEE80211_TX_PS_BUFFERED; tx.channel = local->hw.conf.channel; info->band = tx.channel->band; diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index ef0560a2346a..556647a910ac 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -1290,7 +1290,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) } } - mod_timer(&local->sta_cleanup, jiffies + 1); + add_timer(&local->sta_cleanup); mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) diff --git a/trunk/net/mac80211/wep.c b/trunk/net/mac80211/wep.c index a1c6bfd55f0f..2ff6d1e3ed21 100644 --- a/trunk/net/mac80211/wep.c +++ b/trunk/net/mac80211/wep.c @@ -30,15 +30,17 @@ int ieee80211_wep_init(struct ieee80211_local *local) /* start WEP IV from a random value */ get_random_bytes(&local->wep_iv, WEP_IV_LEN); - local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); + local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_tx_tfm)) { local->wep_rx_tfm = ERR_PTR(-EINVAL); return PTR_ERR(local->wep_tx_tfm); } - local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); + local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_rx_tfm)) { - crypto_free_cipher(local->wep_tx_tfm); + crypto_free_blkcipher(local->wep_tx_tfm); local->wep_tx_tfm = ERR_PTR(-EINVAL); return PTR_ERR(local->wep_rx_tfm); } @@ -49,9 +51,9 @@ int ieee80211_wep_init(struct ieee80211_local *local) void ieee80211_wep_free(struct ieee80211_local *local) { if (!IS_ERR(local->wep_tx_tfm)) - crypto_free_cipher(local->wep_tx_tfm); + crypto_free_blkcipher(local->wep_tx_tfm); if (!IS_ERR(local->wep_rx_tfm)) - crypto_free_cipher(local->wep_rx_tfm); + crypto_free_blkcipher(local->wep_rx_tfm); } static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) @@ -125,11 +127,12 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, /* Perform WEP encryption using given key. data buffer must have tailroom * for 4-byte ICV. data_len must not include this ICV. Note: this function * does _not_ add IV. data = RC4(data | CRC32(data)) */ -int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len) { + struct blkcipher_desc desc = { .tfm = tfm }; + struct scatterlist sg; __le32 icv; - int i; if (IS_ERR(tfm)) return -1; @@ -137,9 +140,9 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, icv = cpu_to_le32(~crc32_le(~0, data, data_len)); put_unaligned(icv, (__le32 *)(data + data_len)); - crypto_cipher_setkey(tfm, rc4key, klen); - for (i = 0; i < data_len + WEP_ICV_LEN; i++) - crypto_cipher_encrypt_one(tfm, data + i, data + i); + crypto_blkcipher_setkey(tfm, rc4key, klen); + sg_init_one(&sg, data, data_len + WEP_ICV_LEN); + crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); return 0; } @@ -183,18 +186,19 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, /* Perform WEP decryption using given key. data buffer includes encrypted * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. * Return 0 on success and -1 on ICV mismatch. */ -int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len) { + struct blkcipher_desc desc = { .tfm = tfm }; + struct scatterlist sg; __le32 crc; - int i; if (IS_ERR(tfm)) return -1; - crypto_cipher_setkey(tfm, rc4key, klen); - for (i = 0; i < data_len + WEP_ICV_LEN; i++) - crypto_cipher_decrypt_one(tfm, data + i, data + i); + crypto_blkcipher_setkey(tfm, rc4key, klen); + sg_init_one(&sg, data, data_len + WEP_ICV_LEN); + crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); crc = cpu_to_le32(~crc32_le(~0, data, data_len)); if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) diff --git a/trunk/net/mac80211/wep.h b/trunk/net/mac80211/wep.h index 01e54840a628..58654ee33518 100644 --- a/trunk/net/mac80211/wep.h +++ b/trunk/net/mac80211/wep.h @@ -18,12 +18,12 @@ int ieee80211_wep_init(struct ieee80211_local *local); void ieee80211_wep_free(struct ieee80211_local *local); -int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len); int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, const u8 *key, int keylen, int keyidx); -int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, size_t klen, u8 *data, size_t data_len); bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c index a94b312dbfac..e73c8cae036b 100644 --- a/trunk/net/mac80211/work.c +++ b/trunk/net/mac80211/work.c @@ -198,8 +198,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, qos_info; + const u8 *ies; size_t offset = 0, noffset; - int i, count, rates_len, supp_rates_len; + int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_supported_band *sband; u32 rates = 0; @@ -284,7 +285,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } /* SSID */ - pos = skb_put(skb, 2 + wk->assoc.ssid_len); + ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); *pos++ = WLAN_EID_SSID; *pos++ = wk->assoc.ssid_len; memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); @@ -294,6 +295,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, if (supp_rates_len > 8) supp_rates_len = 8; + len = sband->n_bitrates; pos = skb_put(skb, supp_rates_len + 2); *pos++ = WLAN_EID_SUPP_RATES; *pos++ = supp_rates_len; diff --git a/trunk/net/rfkill/Kconfig b/trunk/net/rfkill/Kconfig index 48464ca13b24..7fce6dfd2180 100644 --- a/trunk/net/rfkill/Kconfig +++ b/trunk/net/rfkill/Kconfig @@ -22,14 +22,3 @@ config RFKILL_INPUT depends on RFKILL depends on INPUT = y || RFKILL = INPUT default y if !EXPERT - -config RFKILL_REGULATOR - tristate "Generic rfkill regulator driver" - depends on RFKILL || !RFKILL - depends on REGULATOR - help - This options enable controlling radio transmitters connected to - voltage regulator using the regulator framework. - - To compile this driver as a module, choose M here: the module will - be called rfkill-regulator. diff --git a/trunk/net/rfkill/Makefile b/trunk/net/rfkill/Makefile index d9a5a58ffd8c..662105352691 100644 --- a/trunk/net/rfkill/Makefile +++ b/trunk/net/rfkill/Makefile @@ -5,4 +5,3 @@ rfkill-y += core.o rfkill-$(CONFIG_RFKILL_INPUT) += input.o obj-$(CONFIG_RFKILL) += rfkill.o -obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o diff --git a/trunk/net/rfkill/rfkill-regulator.c b/trunk/net/rfkill/rfkill-regulator.c deleted file mode 100644 index 18dc512a10f3..000000000000 --- a/trunk/net/rfkill/rfkill-regulator.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * rfkill-regulator.c - Regulator consumer driver for rfkill - * - * Copyright (C) 2009 Guiming Zhuo - * Copyright (C) 2011 Antonio Ospite - * - * Implementation inspired by leds-regulator driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -struct rfkill_regulator_data { - struct rfkill *rf_kill; - bool reg_enabled; - - struct regulator *vcc; -}; - -static int rfkill_regulator_set_block(void *data, bool blocked) -{ - struct rfkill_regulator_data *rfkill_data = data; - - pr_debug("%s: blocked: %d\n", __func__, blocked); - - if (blocked) { - if (rfkill_data->reg_enabled) { - regulator_disable(rfkill_data->vcc); - rfkill_data->reg_enabled = 0; - } - } else { - if (!rfkill_data->reg_enabled) { - regulator_enable(rfkill_data->vcc); - rfkill_data->reg_enabled = 1; - } - } - - pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__, - regulator_is_enabled(rfkill_data->vcc)); - - return 0; -} - -struct rfkill_ops rfkill_regulator_ops = { - .set_block = rfkill_regulator_set_block, -}; - -static int __devinit rfkill_regulator_probe(struct platform_device *pdev) -{ - struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data; - struct rfkill_regulator_data *rfkill_data; - struct regulator *vcc; - struct rfkill *rf_kill; - int ret = 0; - - if (pdata == NULL) { - dev_err(&pdev->dev, "no platform data\n"); - return -ENODEV; - } - - if (pdata->name == NULL || pdata->type == 0) { - dev_err(&pdev->dev, "invalid name or type in platform data\n"); - return -EINVAL; - } - - vcc = regulator_get_exclusive(&pdev->dev, "vrfkill"); - if (IS_ERR(vcc)) { - dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name); - ret = PTR_ERR(vcc); - goto out; - } - - rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL); - if (rfkill_data == NULL) { - ret = -ENOMEM; - goto err_data_alloc; - } - - rf_kill = rfkill_alloc(pdata->name, &pdev->dev, - pdata->type, - &rfkill_regulator_ops, rfkill_data); - if (rf_kill == NULL) { - dev_err(&pdev->dev, "Cannot alloc rfkill device\n"); - ret = -ENOMEM; - goto err_rfkill_alloc; - } - - if (regulator_is_enabled(vcc)) { - dev_dbg(&pdev->dev, "Regulator already enabled\n"); - rfkill_data->reg_enabled = 1; - } - rfkill_data->vcc = vcc; - rfkill_data->rf_kill = rf_kill; - - ret = rfkill_register(rf_kill); - if (ret) { - dev_err(&pdev->dev, "Cannot register rfkill device\n"); - goto err_rfkill_register; - } - - platform_set_drvdata(pdev, rfkill_data); - dev_info(&pdev->dev, "%s initialized\n", pdata->name); - - return 0; - -err_rfkill_register: - rfkill_destroy(rf_kill); -err_rfkill_alloc: - kfree(rfkill_data); -err_data_alloc: - regulator_put(vcc); -out: - return ret; -} - -static int __devexit rfkill_regulator_remove(struct platform_device *pdev) -{ - struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev); - struct rfkill *rf_kill = rfkill_data->rf_kill; - - rfkill_unregister(rf_kill); - rfkill_destroy(rf_kill); - regulator_put(rfkill_data->vcc); - kfree(rfkill_data); - - return 0; -} - -static struct platform_driver rfkill_regulator_driver = { - .probe = rfkill_regulator_probe, - .remove = __devexit_p(rfkill_regulator_remove), - .driver = { - .name = "rfkill-regulator", - .owner = THIS_MODULE, - }, -}; - -static int __init rfkill_regulator_init(void) -{ - return platform_driver_register(&rfkill_regulator_driver); -} -module_init(rfkill_regulator_init); - -static void __exit rfkill_regulator_exit(void) -{ - platform_driver_unregister(&rfkill_regulator_driver); -} -module_exit(rfkill_regulator_exit); - -MODULE_AUTHOR("Guiming Zhuo "); -MODULE_AUTHOR("Antonio Ospite "); -MODULE_DESCRIPTION("Regulator consumer driver for rfkill"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:rfkill-regulator"); diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index bbf1fa11107a..fe01de29bfe8 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -46,11 +46,6 @@ static struct dentry *ieee80211_debugfs_dir; /* for the cleanup, scan and event works */ struct workqueue_struct *cfg80211_wq; -static bool cfg80211_disable_40mhz_24ghz; -module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); -MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, - "Disable 40MHz support in the 2.4GHz band"); - /* requires cfg80211_mutex to be held! */ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) { @@ -455,18 +450,6 @@ int wiphy_register(struct wiphy *wiphy) if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) return -EINVAL; - /* - * Since cfg80211_disable_40mhz_24ghz is global, we can - * modify the sband's ht data even if the driver uses a - * global structure for that. - */ - if (cfg80211_disable_40mhz_24ghz && - band == IEEE80211_BAND_2GHZ && - sband->ht_cap.ht_supported) { - sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; - } - /* * Since we use a u32 for rate bitmaps in * ieee80211_get_response_rate, we cannot diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index 5c116083eeca..73e39c171ffb 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -1,6 +1,5 @@ #include #include -#include "nl80211.h" #include "core.h" /* Default values, timeouts in ms */ @@ -54,9 +53,8 @@ const struct mesh_config default_mesh_config = { const struct mesh_setup default_mesh_setup = { .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, .path_metric = IEEE80211_PATH_METRIC_AIRTIME, - .ie = NULL, - .ie_len = 0, - .is_secure = false, + .vendor_ie = NULL, + .vendor_ie_len = 0, }; int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, @@ -74,10 +72,6 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) return -EOPNOTSUPP; - if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && - setup->is_secure) - return -EOPNOTSUPP; - if (wdev->mesh_id_len) return -EALREADY; @@ -111,19 +105,6 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, return err; } -void cfg80211_notify_new_peer_candidate(struct net_device *dev, - const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - - if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) - return; - - nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, - macaddr, ie, ie_len, gfp); -} -EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); - static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, struct net_device *dev) { diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 16881fea4ce6..aa5df8865ff7 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -770,15 +770,6 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, } EXPORT_SYMBOL(cfg80211_new_sta); -void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) -{ - struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); -} -EXPORT_SYMBOL(cfg80211_del_sta); - struct cfg80211_mgmt_registration { struct list_head list; diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 0efa7fd01150..4ebce4284e9d 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -124,7 +124,6 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, - [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG }, [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, .len = NL80211_HT_CAPABILITY_LEN }, @@ -595,8 +594,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); - if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) - NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -1925,7 +1922,6 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, - [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG }, }; static int parse_station_flags(struct genl_info *info, @@ -2006,7 +2002,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, const u8 *mac_addr, struct station_info *sinfo) { void *hdr; - struct nlattr *sinfoattr, *bss_param; + struct nlattr *sinfoattr; hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); if (!hdr) @@ -2020,9 +2016,6 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); if (!sinfoattr) goto nla_put_failure; - if (sinfo->filled & STATION_INFO_CONNECTED_TIME) - NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME, - sinfo->connected_time); if (sinfo->filled & STATION_INFO_INACTIVE_TIME) NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, sinfo->inactive_time); @@ -2069,25 +2062,6 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, if (sinfo->filled & STATION_INFO_TX_FAILED) NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, sinfo->tx_failed); - if (sinfo->filled & STATION_INFO_BSS_PARAM) { - bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); - if (!bss_param) - goto nla_put_failure; - - if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) - NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); - if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) - NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); - if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) - NLA_PUT_FLAG(msg, - NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); - NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, - sinfo->bss_param.dtim_period); - NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, - sinfo->bss_param.beacon_interval); - - nla_nest_end(msg, bss_param); - } nla_nest_end(msg, sinfoattr); return genlmsg_end(msg, hdr); @@ -2288,9 +2262,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) err = -EINVAL; if (params.supported_rates) err = -EINVAL; - if (params.sta_flags_mask & - ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | - BIT(NL80211_STA_FLAG_AUTHORIZED))) + if (params.sta_flags_mask) err = -EINVAL; break; default: @@ -2352,16 +2324,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); - if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) - params.plink_action = - nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); - if (parse_station_flags(info, ¶ms)) return -EINVAL; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) return -EINVAL; @@ -2837,8 +2804,7 @@ static const struct nla_policy nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, - [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, - [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, + [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, }; @@ -2940,16 +2906,14 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, IEEE80211_PATH_METRIC_VENDOR : IEEE80211_PATH_METRIC_AIRTIME; - - if (tb[NL80211_MESH_SETUP_IE]) { + if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) { struct nlattr *ieattr = - tb[NL80211_MESH_SETUP_IE]; + tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]; if (!is_valid_ie_attr(ieattr)) return -EINVAL; - setup->ie = nla_data(ieattr); - setup->ie_len = nla_len(ieattr); + setup->vendor_ie = nla_data(ieattr); + setup->vendor_ie_len = nla_len(ieattr); } - setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); return 0; } @@ -5821,44 +5785,6 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - const u8 *macaddr, const u8* ie, u8 ie_len, - gfp_t gfp) -{ - struct sk_buff *msg; - void *hdr; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE); - if (!hdr) { - nlmsg_free(msg); - return; - } - - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr); - if (ie_len && ie) - NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie); - - if (genlmsg_end(msg, hdr) < 0) { - nlmsg_free(msg); - return; - } - - genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, - nl80211_mlme_mcgrp.id, gfp); - return; - - nla_put_failure: - genlmsg_cancel(msg, hdr); - nlmsg_free(msg); -} - void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, enum nl80211_key_type key_type, int key_id, @@ -6040,40 +5966,6 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, nl80211_mlme_mcgrp.id, gfp); } -void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *mac_addr, - gfp_t gfp) -{ - struct sk_buff *msg; - void *hdr; - - msg = nlmsg_new(NLMSG_GOODSIZE, gfp); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION); - if (!hdr) { - nlmsg_free(msg); - return; - } - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); - - if (genlmsg_end(msg, hdr) < 0) { - nlmsg_free(msg); - return; - } - - genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, - nl80211_mlme_mcgrp.id, gfp); - return; - - nla_put_failure: - genlmsg_cancel(msg, hdr); - nlmsg_free(msg); -} - int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct net_device *netdev, u32 nlpid, int freq, const u8 *buf, size_t len, gfp_t gfp) diff --git a/trunk/net/wireless/nl80211.h b/trunk/net/wireless/nl80211.h index f2af6955a665..e3f7fa886966 100644 --- a/trunk/net/wireless/nl80211.h +++ b/trunk/net/wireless/nl80211.h @@ -50,10 +50,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, struct net_device *netdev, u16 reason, const u8 *ie, size_t ie_len, bool from_ap); -void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - const u8 *macaddr, const u8* ie, u8 ie_len, - gfp_t gfp); void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, @@ -83,9 +79,6 @@ void nl80211_send_remain_on_channel_cancel( void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); -void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *mac_addr, - gfp_t gfp); int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct net_device *netdev, u32 nlpid, int freq, diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 8982053f9961..3332d5bce317 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -106,9 +106,6 @@ struct reg_beacon { static void reg_todo(struct work_struct *work); static DECLARE_WORK(reg_work, reg_todo); -static void reg_timeout_work(struct work_struct *work); -static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); - /* We keep a static world regulatory domain in case of the absence of CRDA */ static const struct ieee80211_regdomain world_regdom = { .n_reg_rules = 5, @@ -1333,9 +1330,6 @@ static void reg_set_request_processed(void) need_more_processing = true; spin_unlock(®_requests_lock); - if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) - cancel_delayed_work_sync(®_timeout); - if (need_more_processing) schedule_work(®_work); } @@ -1446,18 +1440,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) r = __regulatory_hint(wiphy, reg_request); /* This is required so that the orig_* parameters are saved */ if (r == -EALREADY && wiphy && - wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { + wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) wiphy_update_regulatory(wiphy, initiator); - return; - } - - /* - * We only time out user hints, given that they should be the only - * source of bogus requests. - */ - if (r != -EALREADY && - reg_request->initiator == NL80211_REGDOM_SET_BY_USER) - schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); } /* @@ -1760,8 +1744,6 @@ static void restore_regulatory_settings(bool reset_user) { char alpha2[2]; struct reg_beacon *reg_beacon, *btmp; - struct regulatory_request *reg_request, *tmp; - LIST_HEAD(tmp_reg_req_list); mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); @@ -1769,25 +1751,6 @@ static void restore_regulatory_settings(bool reset_user) reset_regdomains(); restore_alpha2(alpha2, reset_user); - /* - * If there's any pending requests we simply - * stash them to a temporary pending queue and - * add then after we've restored regulatory - * settings. - */ - spin_lock(®_requests_lock); - if (!list_empty(®_requests_list)) { - list_for_each_entry_safe(reg_request, tmp, - ®_requests_list, list) { - if (reg_request->initiator != - NL80211_REGDOM_SET_BY_USER) - continue; - list_del(®_request->list); - list_add_tail(®_request->list, &tmp_reg_req_list); - } - } - spin_unlock(®_requests_lock); - /* Clear beacon hints */ spin_lock_bh(®_pending_beacons_lock); if (!list_empty(®_pending_beacons)) { @@ -1822,32 +1785,9 @@ static void restore_regulatory_settings(bool reset_user) */ if (is_an_alpha2(alpha2)) regulatory_hint_user(user_alpha2); - - if (list_empty(&tmp_reg_req_list)) - return; - - mutex_lock(&cfg80211_mutex); - mutex_lock(®_mutex); - - spin_lock(®_requests_lock); - list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) { - REG_DBG_PRINT("Adding request for country %c%c back " - "into the queue\n", - reg_request->alpha2[0], - reg_request->alpha2[1]); - list_del(®_request->list); - list_add_tail(®_request->list, ®_requests_list); - } - spin_unlock(®_requests_lock); - - mutex_unlock(®_mutex); - mutex_unlock(&cfg80211_mutex); - - REG_DBG_PRINT("Kicking the queue\n"); - - schedule_work(®_work); } + void regulatory_hint_disconnect(void) { REG_DBG_PRINT("All devices are disconnected, going to " @@ -2185,13 +2125,6 @@ void reg_device_remove(struct wiphy *wiphy) mutex_unlock(®_mutex); } -static void reg_timeout_work(struct work_struct *work) -{ - REG_DBG_PRINT("Timeout while waiting for CRDA to reply, " - "restoring regulatory settings"); - restore_regulatory_settings(true); -} - int __init regulatory_init(void) { int err = 0; @@ -2245,7 +2178,6 @@ void /* __init_or_exit */ regulatory_exit(void) struct reg_beacon *reg_beacon, *btmp; cancel_work_sync(®_work); - cancel_delayed_work_sync(®_timeout); mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex);