Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: Documentation/feature-removal-schedule.txt drivers/net/wireless/ath/ath5k/phy.c
This commit is contained in:
commit
33e2bf6aa1
|
@ -0,0 +1,29 @@
|
|||
rfkill - radio frequency (RF) connector kill switch support
|
||||
|
||||
For details to this subsystem look at Documentation/rfkill.txt.
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/state
|
||||
Date: 09-Jul-2007
|
||||
KernelVersion v2.6.22
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: Current state of the transmitter.
|
||||
This file is deprecated and sheduled to be removed in 2014,
|
||||
because its not possible to express the 'soft and hard block'
|
||||
state of the rfkill driver.
|
||||
Values: A numeric value.
|
||||
0: RFKILL_STATE_SOFT_BLOCKED
|
||||
transmitter is turned off by software
|
||||
1: RFKILL_STATE_UNBLOCKED
|
||||
transmitter is (potentially) active
|
||||
2: RFKILL_STATE_HARD_BLOCKED
|
||||
transmitter is forced off by something outside of
|
||||
the driver's control.
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/claim
|
||||
Date: 09-Jul-2007
|
||||
KernelVersion v2.6.22
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: This file is deprecated because there no longer is a way to
|
||||
claim just control over a single rfkill instance.
|
||||
This file is scheduled to be removed in 2012.
|
||||
Values: 0: Kernel handles events
|
|
@ -0,0 +1,67 @@
|
|||
rfkill - radio frequency (RF) connector kill switch support
|
||||
|
||||
For details to this subsystem look at Documentation/rfkill.txt.
|
||||
|
||||
For the deprecated /sys/class/rfkill/*/state and
|
||||
/sys/class/rfkill/*/claim knobs of this interface look in
|
||||
Documentation/ABI/obsolete/sysfs-class-rfkill.
|
||||
|
||||
What: /sys/class/rfkill
|
||||
Date: 09-Jul-2007
|
||||
KernelVersion: v2.6.22
|
||||
Contact: linux-wireless@vger.kernel.org,
|
||||
Description: The rfkill class subsystem folder.
|
||||
Each registered rfkill driver is represented by an rfkillX
|
||||
subfolder (X being an integer > 0).
|
||||
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/name
|
||||
Date: 09-Jul-2007
|
||||
KernelVersion v2.6.22
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: Name assigned by driver to this key (interface or driver name).
|
||||
Values: arbitrary string.
|
||||
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/type
|
||||
Date: 09-Jul-2007
|
||||
KernelVersion v2.6.22
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: Driver type string ("wlan", "bluetooth", etc).
|
||||
Values: See include/linux/rfkill.h.
|
||||
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/persistent
|
||||
Date: 09-Jul-2007
|
||||
KernelVersion v2.6.22
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: Whether the soft blocked state is initialised from non-volatile
|
||||
storage at startup.
|
||||
Values: A numeric value.
|
||||
0: false
|
||||
1: true
|
||||
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/hard
|
||||
Date: 12-March-2010
|
||||
KernelVersion v2.6.34
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: Current hardblock state. This file is read only.
|
||||
Values: A numeric value.
|
||||
0: inactive
|
||||
The transmitter is (potentially) active.
|
||||
1: active
|
||||
The transmitter is forced off by something outside of
|
||||
the driver's control.
|
||||
|
||||
|
||||
What: /sys/class/rfkill/rfkill[0-9]+/soft
|
||||
Date: 12-March-2010
|
||||
KernelVersion v2.6.34
|
||||
Contact: linux-wireless@vger.kernel.org
|
||||
Description: Current softblock state. This file is read and write.
|
||||
Values: A numeric value.
|
||||
0: inactive
|
||||
The transmitter is (potentially) active.
|
||||
1: active
|
||||
The transmitter is turned off by software.
|
|
@ -520,6 +520,7 @@ Who: Hans de Goede <hdegoede@redhat.com>
|
|||
|
||||
----------------------------
|
||||
|
||||
|
||||
What: corgikbd, spitzkbd, tosakbd driver
|
||||
When: 2.6.35
|
||||
Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c
|
||||
|
@ -543,6 +544,24 @@ Who: Eric Miao <eric.y.miao@gmail.com>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: sysfs-class-rfkill state file
|
||||
When: Feb 2014
|
||||
Files: net/rfkill/core.c
|
||||
Why: Documented as obsolete since Feb 2010. This file is limited to 3
|
||||
states while the rfkill drivers can have 4 states.
|
||||
Who: anybody or Florian Mickler <florian@mickler.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: sysfs-class-rfkill claim file
|
||||
When: Feb 2012
|
||||
Files: net/rfkill/core.c
|
||||
Why: It is not possible to claim an rfkill driver since 2007. This is
|
||||
Documented as obsolete since Feb 2010.
|
||||
Who: anybody or Florian Mickler <florian@mickler.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: capifs
|
||||
When: February 2011
|
||||
Files: drivers/isdn/capi/capifs.*
|
||||
|
|
|
@ -99,37 +99,15 @@ system. Also, it is possible to switch all rfkill drivers (or all drivers of
|
|||
a specified type) into a state which also updates the default state for
|
||||
hotplugged devices.
|
||||
|
||||
After an application opens /dev/rfkill, it can read the current state of
|
||||
all devices, and afterwards can poll the descriptor for hotplug or state
|
||||
change events.
|
||||
After an application opens /dev/rfkill, it can read the current state of all
|
||||
devices. Changes can be either obtained by either polling the descriptor for
|
||||
hotplug or state change events or by listening for uevents emitted by the
|
||||
rfkill core framework.
|
||||
|
||||
Applications must ignore operations (the "op" field) they do not handle,
|
||||
this allows the API to be extended in the future.
|
||||
Additionally, each rfkill device is registered in sysfs and emits uevents.
|
||||
|
||||
Additionally, each rfkill device is registered in sysfs and there has the
|
||||
following attributes:
|
||||
|
||||
name: Name assigned by driver to this key (interface or driver name).
|
||||
type: Driver type string ("wlan", "bluetooth", etc).
|
||||
persistent: Whether the soft blocked state is initialised from
|
||||
non-volatile storage at startup.
|
||||
state: Current state of the transmitter
|
||||
0: RFKILL_STATE_SOFT_BLOCKED
|
||||
transmitter is turned off by software
|
||||
1: RFKILL_STATE_UNBLOCKED
|
||||
transmitter is (potentially) active
|
||||
2: RFKILL_STATE_HARD_BLOCKED
|
||||
transmitter is forced off by something outside of
|
||||
the driver's control.
|
||||
This file is deprecated because it can only properly show
|
||||
three of the four possible states, soft-and-hard-blocked is
|
||||
missing.
|
||||
claim: 0: Kernel handles events
|
||||
This file is deprecated because there no longer is a way to
|
||||
claim just control over a single rfkill instance.
|
||||
|
||||
rfkill devices also issue uevents (with an action of "change"), with the
|
||||
following environment variables set:
|
||||
rfkill devices issue uevents (with an action of "change"), with the following
|
||||
environment variables set:
|
||||
|
||||
RFKILL_NAME
|
||||
RFKILL_STATE
|
||||
|
@ -137,3 +115,7 @@ RFKILL_TYPE
|
|||
|
||||
The contents of these variables corresponds to the "name", "state" and
|
||||
"type" sysfs files explained above.
|
||||
|
||||
|
||||
For further details consult Documentation/ABI/stable/dev-rfkill and
|
||||
Documentation/ABI/stable/sysfs-class-rfkill.
|
||||
|
|
|
@ -2876,7 +2876,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
|||
ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0;
|
||||
ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0;
|
||||
|
||||
airo_print_info(dev->name, "Firmware version %x.%x.%02x",
|
||||
airo_print_info(dev->name, "Firmware version %x.%x.%02d",
|
||||
((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF),
|
||||
(le16_to_cpu(cap_rid.softVer) & 0xFF),
|
||||
le16_to_cpu(cap_rid.softSubVer));
|
||||
|
@ -3193,19 +3193,26 @@ static void airo_print_status(const char *devname, u16 status)
|
|||
{
|
||||
u8 reason = status & 0xFF;
|
||||
|
||||
switch (status) {
|
||||
switch (status & 0xFF00) {
|
||||
case STAT_NOBEACON:
|
||||
airo_print_dbg(devname, "link lost (missed beacons)");
|
||||
break;
|
||||
case STAT_MAXRETRIES:
|
||||
case STAT_MAXARL:
|
||||
airo_print_dbg(devname, "link lost (max retries)");
|
||||
break;
|
||||
case STAT_FORCELOSS:
|
||||
airo_print_dbg(devname, "link lost (local choice)");
|
||||
break;
|
||||
case STAT_TSFSYNC:
|
||||
airo_print_dbg(devname, "link lost (TSF sync lost)");
|
||||
switch (status) {
|
||||
case STAT_NOBEACON:
|
||||
airo_print_dbg(devname, "link lost (missed beacons)");
|
||||
break;
|
||||
case STAT_MAXRETRIES:
|
||||
case STAT_MAXARL:
|
||||
airo_print_dbg(devname, "link lost (max retries)");
|
||||
break;
|
||||
case STAT_FORCELOSS:
|
||||
airo_print_dbg(devname, "link lost (local choice)");
|
||||
break;
|
||||
case STAT_TSFSYNC:
|
||||
airo_print_dbg(devname, "link lost (TSF sync lost)");
|
||||
break;
|
||||
default:
|
||||
airo_print_dbg(devname, "unknow status %x\n", status);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case STAT_DEAUTH:
|
||||
airo_print_dbg(devname, "deauthenticated (reason: %d)", reason);
|
||||
|
@ -3221,7 +3228,11 @@ static void airo_print_status(const char *devname, u16 status)
|
|||
airo_print_dbg(devname, "authentication failed (reason: %d)",
|
||||
reason);
|
||||
break;
|
||||
case STAT_ASSOC:
|
||||
case STAT_REASSOC:
|
||||
break;
|
||||
default:
|
||||
airo_print_dbg(devname, "unknow status %x\n", status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,7 +202,6 @@
|
|||
#define AR5K_TUNE_MAX_TXPOWER 63
|
||||
#define AR5K_TUNE_DEFAULT_TXPOWER 25
|
||||
#define AR5K_TUNE_TPC_TXPOWER false
|
||||
#define AR5K_TUNE_HWTXTRIES 4
|
||||
|
||||
#define AR5K_INIT_CARR_SENSE_EN 1
|
||||
|
||||
|
@ -614,28 +613,6 @@ struct ath5k_rx_status {
|
|||
#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/
|
||||
#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* struct ath5k_beacon_state - Per-station beacon timer state.
|
||||
* @bs_interval: in TU's, can also include the above flags
|
||||
* @bs_cfp_max_duration: if non-zero hw is setup to coexist with a
|
||||
* Point Coordination Function capable AP
|
||||
*/
|
||||
struct ath5k_beacon_state {
|
||||
u32 bs_next_beacon;
|
||||
u32 bs_next_dtim;
|
||||
u32 bs_interval;
|
||||
u8 bs_dtim_period;
|
||||
u8 bs_cfp_period;
|
||||
u16 bs_cfp_max_duration;
|
||||
u16 bs_cfp_du_remain;
|
||||
u16 bs_tim_offset;
|
||||
u16 bs_sleep_duration;
|
||||
u16 bs_bmiss_threshold;
|
||||
u32 bs_cfp_next;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* TSF to TU conversion:
|
||||
|
@ -1028,7 +1005,6 @@ struct ath5k_nfcal_hist
|
|||
|
||||
/* TODO: Clean up and merge with ath5k_softc */
|
||||
struct ath5k_hw {
|
||||
u32 ah_magic;
|
||||
struct ath_common common;
|
||||
|
||||
struct ath5k_softc *ah_sc;
|
||||
|
@ -1036,7 +1012,6 @@ struct ath5k_hw {
|
|||
|
||||
enum ath5k_int ah_imr;
|
||||
|
||||
enum nl80211_iftype ah_op_mode;
|
||||
struct ieee80211_channel *ah_current_channel;
|
||||
bool ah_turbo;
|
||||
bool ah_calibration;
|
||||
|
@ -1049,7 +1024,6 @@ struct ath5k_hw {
|
|||
u32 ah_phy;
|
||||
u32 ah_mac_srev;
|
||||
u16 ah_mac_version;
|
||||
u16 ah_mac_revision;
|
||||
u16 ah_phy_revision;
|
||||
u16 ah_radio_5ghz_revision;
|
||||
u16 ah_radio_2ghz_revision;
|
||||
|
@ -1071,8 +1045,6 @@ struct ath5k_hw {
|
|||
u8 ah_def_ant;
|
||||
bool ah_software_retry;
|
||||
|
||||
int ah_gpio_npins;
|
||||
|
||||
struct ath5k_capabilities ah_capabilities;
|
||||
|
||||
struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];
|
||||
|
@ -1141,9 +1113,9 @@ struct ath5k_hw {
|
|||
int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
||||
u32 size, unsigned int flags);
|
||||
int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
|
||||
unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
|
||||
unsigned int, unsigned int, int, enum ath5k_pkt_type,
|
||||
unsigned int, unsigned int, unsigned int, unsigned int,
|
||||
unsigned int, unsigned int, unsigned int);
|
||||
unsigned int, unsigned int, unsigned int, unsigned int);
|
||||
int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
|
||||
unsigned int, unsigned int, unsigned int, unsigned int,
|
||||
unsigned int, unsigned int);
|
||||
|
@ -1158,158 +1130,147 @@ struct ath5k_hw {
|
|||
*/
|
||||
|
||||
/* Attach/Detach Functions */
|
||||
extern int ath5k_hw_attach(struct ath5k_softc *sc);
|
||||
extern void ath5k_hw_detach(struct ath5k_hw *ah);
|
||||
int ath5k_hw_attach(struct ath5k_softc *sc);
|
||||
void ath5k_hw_detach(struct ath5k_hw *ah);
|
||||
|
||||
/* LED functions */
|
||||
extern int ath5k_init_leds(struct ath5k_softc *sc);
|
||||
extern void ath5k_led_enable(struct ath5k_softc *sc);
|
||||
extern void ath5k_led_off(struct ath5k_softc *sc);
|
||||
extern void ath5k_unregister_leds(struct ath5k_softc *sc);
|
||||
int ath5k_init_leds(struct ath5k_softc *sc);
|
||||
void ath5k_led_enable(struct ath5k_softc *sc);
|
||||
void ath5k_led_off(struct ath5k_softc *sc);
|
||||
void ath5k_unregister_leds(struct ath5k_softc *sc);
|
||||
|
||||
/* Reset Functions */
|
||||
extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
|
||||
extern int ath5k_hw_on_hold(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
|
||||
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
|
||||
int ath5k_hw_on_hold(struct ath5k_hw *ah);
|
||||
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
||||
struct ieee80211_channel *channel, bool change_channel);
|
||||
int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
|
||||
bool is_set);
|
||||
/* Power management functions */
|
||||
extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
|
||||
|
||||
/* DMA Related Functions */
|
||||
extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
|
||||
extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
|
||||
extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
|
||||
extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
|
||||
extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
|
||||
extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
|
||||
void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
|
||||
int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
|
||||
u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
|
||||
void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
|
||||
int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
|
||||
int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
|
||||
u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
|
||||
int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
|
||||
u32 phys_addr);
|
||||
extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
|
||||
int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
|
||||
/* Interrupt handling */
|
||||
extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
|
||||
extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum
|
||||
ath5k_int new_mask);
|
||||
extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
|
||||
bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
|
||||
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
|
||||
enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
|
||||
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
|
||||
struct ieee80211_low_level_stats *stats);
|
||||
|
||||
/* EEPROM access functions */
|
||||
extern int ath5k_eeprom_init(struct ath5k_hw *ah);
|
||||
extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
|
||||
extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
|
||||
extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
|
||||
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 */
|
||||
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
|
||||
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
|
||||
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
|
||||
/* BSSID Functions */
|
||||
extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
|
||||
extern void ath5k_hw_set_associd(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
|
||||
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
|
||||
void ath5k_hw_set_associd(struct ath5k_hw *ah);
|
||||
void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
|
||||
/* Receive start/stop functions */
|
||||
extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
|
||||
void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
|
||||
void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
|
||||
/* RX Filter functions */
|
||||
extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
|
||||
extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
|
||||
extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
|
||||
extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
|
||||
void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
|
||||
u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
|
||||
void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
|
||||
/* Beacon control functions */
|
||||
extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
|
||||
extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
|
||||
extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
|
||||
#if 0
|
||||
extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state);
|
||||
extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
|
||||
#endif
|
||||
u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
|
||||
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
|
||||
void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
|
||||
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
|
||||
/* ACK bit rate */
|
||||
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
|
||||
/* ACK/CTS Timeouts */
|
||||
extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
|
||||
extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
|
||||
extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
|
||||
/* Clock rate related functions */
|
||||
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
|
||||
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
|
||||
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
|
||||
/* Key table (WEP) functions */
|
||||
extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
|
||||
extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
|
||||
extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
|
||||
extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
|
||||
int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
|
||||
int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
|
||||
const struct ieee80211_key_conf *key, const u8 *mac);
|
||||
int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
|
||||
|
||||
/* Queue Control Unit, DFS Control Unit Functions */
|
||||
extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
|
||||
extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
|
||||
const struct ath5k_txq_info *queue_info);
|
||||
extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
|
||||
enum ath5k_tx_queue queue_type,
|
||||
struct ath5k_txq_info *queue_info);
|
||||
extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
|
||||
extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
|
||||
extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
|
||||
extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
|
||||
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
|
||||
struct ath5k_txq_info *queue_info);
|
||||
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
|
||||
const struct ath5k_txq_info *queue_info);
|
||||
int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
|
||||
enum ath5k_tx_queue queue_type,
|
||||
struct ath5k_txq_info *queue_info);
|
||||
u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
|
||||
void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
|
||||
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
|
||||
int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
|
||||
|
||||
/* Hardware Descriptor Functions */
|
||||
extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
|
||||
int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
|
||||
|
||||
/* GPIO Functions */
|
||||
extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
|
||||
extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
|
||||
extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
|
||||
extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
|
||||
extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
|
||||
extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
|
||||
void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
|
||||
int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
|
||||
int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
|
||||
u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
|
||||
int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
|
||||
void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
|
||||
u32 interrupt_level);
|
||||
|
||||
/* rfkill Functions */
|
||||
extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
|
||||
extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
|
||||
void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
|
||||
void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
|
||||
|
||||
/* Misc functions */
|
||||
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
|
||||
extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
|
||||
extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
|
||||
int ath5k_hw_get_capability(struct ath5k_hw *ah,
|
||||
enum ath5k_capability_type cap_type, u32 capability,
|
||||
u32 *result);
|
||||
int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
|
||||
int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
|
||||
|
||||
/* Initial register settings functions */
|
||||
extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
|
||||
int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
|
||||
|
||||
/* Initialize RF */
|
||||
extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int mode);
|
||||
extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
|
||||
extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
|
||||
int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int mode);
|
||||
int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
|
||||
enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
|
||||
int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
|
||||
/* PHY/RF channel functions */
|
||||
extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
|
||||
extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
||||
bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
|
||||
int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
||||
/* PHY calibration */
|
||||
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
||||
extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
|
||||
extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
|
||||
int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel);
|
||||
void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
|
||||
/* Spur mitigation */
|
||||
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel);
|
||||
struct ieee80211_channel *channel);
|
||||
void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel);
|
||||
struct ieee80211_channel *channel);
|
||||
/* Misc PHY functions */
|
||||
extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
|
||||
extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
|
||||
u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
|
||||
int ath5k_hw_phy_disable(struct ath5k_hw *ah);
|
||||
/* Antenna control */
|
||||
extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode);
|
||||
extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant);
|
||||
extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
|
||||
void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode);
|
||||
/* TX power setup */
|
||||
extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower);
|
||||
extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
|
||||
int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
||||
u8 ee_mode, u8 txpower);
|
||||
int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
|
||||
|
||||
/*
|
||||
* Functions used internaly
|
||||
|
@ -1335,29 +1296,6 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
|
|||
iowrite32(val, ah->ah_iobase + reg);
|
||||
}
|
||||
|
||||
#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
|
||||
/*
|
||||
* Check if a register write has been completed
|
||||
*/
|
||||
static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
|
||||
u32 val, bool is_set)
|
||||
{
|
||||
int i;
|
||||
u32 data;
|
||||
|
||||
for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
|
||||
data = ath5k_hw_reg_read(ah, reg);
|
||||
if (is_set && (data & flag))
|
||||
break;
|
||||
else if ((data & flag) == val)
|
||||
break;
|
||||
udelay(15);
|
||||
}
|
||||
|
||||
return (i <= 0) ? -EAGAIN : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
|
||||
{
|
||||
u32 retval = 0, bit, i;
|
||||
|
@ -1370,9 +1308,4 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static inline int ath5k_pad_size(int hdrlen)
|
||||
{
|
||||
return (hdrlen < 24) ? 0 : hdrlen & 3;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -113,7 +113,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||
/*
|
||||
* HW information
|
||||
*/
|
||||
ah->ah_op_mode = NL80211_IFTYPE_STATION;
|
||||
ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
|
||||
ah->ah_turbo = false;
|
||||
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
||||
|
@ -123,6 +122,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||
ah->ah_cw_min = AR5K_TUNE_CWMIN;
|
||||
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
|
||||
ah->ah_software_retry = false;
|
||||
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
|
||||
|
||||
/*
|
||||
* Find the mac version
|
||||
|
@ -148,7 +148,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||
/* Get MAC, PHY and RADIO revisions */
|
||||
ah->ah_mac_srev = srev;
|
||||
ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
|
||||
ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
|
||||
ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
|
||||
0xffffffff;
|
||||
ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
|
||||
|
@ -327,7 +326,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
|
||||
memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
|
||||
ath5k_hw_set_associd(ah);
|
||||
ath5k_hw_set_opmode(ah);
|
||||
ath5k_hw_set_opmode(ah, sc->opmode);
|
||||
|
||||
ath5k_hw_rfgain_opt_init(ah);
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
|
|||
static int ath5k_pci_suspend(struct device *dev);
|
||||
static int ath5k_pci_resume(struct device *dev);
|
||||
|
||||
SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
|
||||
static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
|
||||
#define ATH5K_PM_OPS (&ath5k_pm_ops)
|
||||
#else
|
||||
#define ATH5K_PM_OPS NULL
|
||||
|
@ -307,7 +307,7 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
|
|||
struct ath5k_buf *bf);
|
||||
static int ath5k_txbuf_setup(struct ath5k_softc *sc,
|
||||
struct ath5k_buf *bf,
|
||||
struct ath5k_txq *txq);
|
||||
struct ath5k_txq *txq, int padsize);
|
||||
static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
|
||||
struct ath5k_buf *bf)
|
||||
{
|
||||
|
@ -1137,8 +1137,6 @@ ath5k_mode_setup(struct ath5k_softc *sc)
|
|||
struct ath5k_hw *ah = sc->ah;
|
||||
u32 rfilt;
|
||||
|
||||
ah->ah_op_mode = sc->opmode;
|
||||
|
||||
/* configure rx filter */
|
||||
rfilt = sc->filter_flags;
|
||||
ath5k_hw_set_rx_filter(ah, rfilt);
|
||||
|
@ -1147,8 +1145,9 @@ ath5k_mode_setup(struct ath5k_softc *sc)
|
|||
ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
|
||||
|
||||
/* configure operational mode */
|
||||
ath5k_hw_set_opmode(ah);
|
||||
ath5k_hw_set_opmode(ah, sc->opmode);
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode);
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
|
||||
}
|
||||
|
||||
|
@ -1271,7 +1270,7 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
|
|||
|
||||
static int
|
||||
ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
|
||||
struct ath5k_txq *txq)
|
||||
struct ath5k_txq *txq, int padsize)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath5k_desc *ds = bf->desc;
|
||||
|
@ -1323,7 +1322,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
|
|||
sc->vif, pktlen, info));
|
||||
}
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
||||
ieee80211_get_hdrlen_from_skb(skb),
|
||||
ieee80211_get_hdrlen_from_skb(skb), padsize,
|
||||
get_hw_packet_type(skb),
|
||||
(sc->power_level * 2),
|
||||
hw_rate,
|
||||
|
@ -1805,6 +1804,67 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute padding position. skb must contains an IEEE 802.11 frame
|
||||
*/
|
||||
static int ath5k_common_padpos(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 frame_control = hdr->frame_control;
|
||||
int padpos = 24;
|
||||
|
||||
if (ieee80211_has_a4(frame_control)) {
|
||||
padpos += ETH_ALEN;
|
||||
}
|
||||
if (ieee80211_is_data_qos(frame_control)) {
|
||||
padpos += IEEE80211_QOS_CTL_LEN;
|
||||
}
|
||||
|
||||
return padpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function expects a 802.11 frame and returns the number of
|
||||
* bytes added, or -1 if we don't have enought header room.
|
||||
*/
|
||||
|
||||
static int ath5k_add_padding(struct sk_buff *skb)
|
||||
{
|
||||
int padpos = ath5k_common_padpos(skb);
|
||||
int padsize = padpos & 3;
|
||||
|
||||
if (padsize && skb->len>padpos) {
|
||||
|
||||
if (skb_headroom(skb) < padsize)
|
||||
return -1;
|
||||
|
||||
skb_push(skb, padsize);
|
||||
memmove(skb->data, skb->data+padsize, padpos);
|
||||
return padsize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function expects a 802.11 frame and returns the number of
|
||||
* bytes removed
|
||||
*/
|
||||
|
||||
static int ath5k_remove_padding(struct sk_buff *skb)
|
||||
{
|
||||
int padpos = ath5k_common_padpos(skb);
|
||||
int padsize = padpos & 3;
|
||||
|
||||
if (padsize && skb->len>=padpos+padsize) {
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
skb_pull(skb, padsize);
|
||||
return padsize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_rx(unsigned long data)
|
||||
{
|
||||
|
@ -1818,8 +1878,6 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
struct ath5k_buf *bf;
|
||||
struct ath5k_desc *ds;
|
||||
int ret;
|
||||
int hdrlen;
|
||||
int padsize;
|
||||
int rx_flag;
|
||||
|
||||
spin_lock(&sc->rxbuflock);
|
||||
|
@ -1844,18 +1902,28 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
break;
|
||||
else if (unlikely(ret)) {
|
||||
ATH5K_ERR(sc, "error in processing rx descriptor\n");
|
||||
sc->stats.rxerr_proc++;
|
||||
spin_unlock(&sc->rxbuflock);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->stats.rx_all_count++;
|
||||
|
||||
if (unlikely(rs.rs_more)) {
|
||||
ATH5K_WARN(sc, "unsupported jumbo\n");
|
||||
sc->stats.rxerr_jumbo++;
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (unlikely(rs.rs_status)) {
|
||||
if (rs.rs_status & AR5K_RXERR_PHY)
|
||||
if (rs.rs_status & AR5K_RXERR_CRC)
|
||||
sc->stats.rxerr_crc++;
|
||||
if (rs.rs_status & AR5K_RXERR_FIFO)
|
||||
sc->stats.rxerr_fifo++;
|
||||
if (rs.rs_status & AR5K_RXERR_PHY) {
|
||||
sc->stats.rxerr_phy++;
|
||||
goto next;
|
||||
}
|
||||
if (rs.rs_status & AR5K_RXERR_DECRYPT) {
|
||||
/*
|
||||
* Decrypt error. If the error occurred
|
||||
|
@ -1867,12 +1935,14 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
*
|
||||
* XXX do key cache faulting
|
||||
*/
|
||||
sc->stats.rxerr_decrypt++;
|
||||
if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
|
||||
!(rs.rs_status & AR5K_RXERR_CRC))
|
||||
goto accept;
|
||||
}
|
||||
if (rs.rs_status & AR5K_RXERR_MIC) {
|
||||
rx_flag |= RX_FLAG_MMIC_ERROR;
|
||||
sc->stats.rxerr_mic++;
|
||||
goto accept;
|
||||
}
|
||||
|
||||
|
@ -1904,12 +1974,8 @@ accept:
|
|||
* bytes and we can optimize this a bit. In addition, we must
|
||||
* not try to remove padding from short control frames that do
|
||||
* not have payload. */
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
padsize = ath5k_pad_size(hdrlen);
|
||||
if (padsize) {
|
||||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
ath5k_remove_padding(skb);
|
||||
|
||||
rxs = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
/*
|
||||
|
@ -1942,6 +2008,12 @@ accept:
|
|||
rxs->signal = rxs->noise + rs.rs_rssi;
|
||||
|
||||
rxs->antenna = rs.rs_antenna;
|
||||
|
||||
if (rs.rs_antenna > 0 && rs.rs_antenna < 5)
|
||||
sc->stats.antenna_rx[rs.rs_antenna]++;
|
||||
else
|
||||
sc->stats.antenna_rx[0]++; /* invalid */
|
||||
|
||||
rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
|
||||
rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
|
||||
|
||||
|
@ -1996,6 +2068,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
|||
break;
|
||||
}
|
||||
|
||||
sc->stats.tx_all_count++;
|
||||
skb = bf->skb;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
bf->skb = NULL;
|
||||
|
@ -2022,13 +2095,30 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
|||
|
||||
if (unlikely(ts.ts_status)) {
|
||||
sc->ll_stats.dot11ACKFailureCount++;
|
||||
if (ts.ts_status & AR5K_TXERR_FILT)
|
||||
if (ts.ts_status & AR5K_TXERR_FILT) {
|
||||
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
sc->stats.txerr_filt++;
|
||||
}
|
||||
if (ts.ts_status & AR5K_TXERR_XRETRY)
|
||||
sc->stats.txerr_retry++;
|
||||
if (ts.ts_status & AR5K_TXERR_FIFO)
|
||||
sc->stats.txerr_fifo++;
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ts.ts_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove MAC header padding before giving the frame
|
||||
* back to mac80211.
|
||||
*/
|
||||
ath5k_remove_padding(skb);
|
||||
|
||||
if (ts.ts_antenna > 0 && ts.ts_antenna < 5)
|
||||
sc->stats.antenna_tx[ts.ts_antenna]++;
|
||||
else
|
||||
sc->stats.antenna_tx[0]++; /* invalid */
|
||||
|
||||
ieee80211_tx_status(sc->hw, skb);
|
||||
|
||||
spin_lock(&sc->txbuflock);
|
||||
|
@ -2072,6 +2162,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
|||
int ret = 0;
|
||||
u8 antenna;
|
||||
u32 flags;
|
||||
const int padsize = 0;
|
||||
|
||||
bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
@ -2119,7 +2210,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
|||
* from tx power (value is in dB units already) */
|
||||
ds->ds_data = bf->skbaddr;
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
|
||||
ieee80211_get_hdrlen_from_skb(skb),
|
||||
ieee80211_get_hdrlen_from_skb(skb), padsize,
|
||||
AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
|
||||
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
|
||||
1, AR5K_TXKEYIX_INVALID,
|
||||
|
@ -2679,7 +2770,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_buf *bf;
|
||||
unsigned long flags;
|
||||
int hdrlen;
|
||||
int padsize;
|
||||
|
||||
ath5k_debug_dump_skb(sc, skb, "TX ", 1);
|
||||
|
@ -2691,17 +2781,11 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
* the hardware expects the header padded to 4 byte boundaries
|
||||
* if this is not the case we add the padding after the header
|
||||
*/
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
padsize = ath5k_pad_size(hdrlen);
|
||||
if (padsize) {
|
||||
|
||||
if (skb_headroom(skb) < padsize) {
|
||||
ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
|
||||
" headroom to pad %d\n", hdrlen, padsize);
|
||||
goto drop_packet;
|
||||
}
|
||||
skb_push(skb, padsize);
|
||||
memmove(skb->data, skb->data+padsize, hdrlen);
|
||||
padsize = ath5k_add_padding(skb);
|
||||
if (padsize < 0) {
|
||||
ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
|
||||
" headroom to pad");
|
||||
goto drop_packet;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sc->txbuflock, flags);
|
||||
|
@ -2720,7 +2804,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
|
||||
bf->skb = skb;
|
||||
|
||||
if (ath5k_txbuf_setup(sc, bf, txq)) {
|
||||
if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
|
||||
bf->skb = NULL;
|
||||
spin_lock_irqsave(&sc->txbuflock, flags);
|
||||
list_add_tail(&bf->list, &sc->txbuf);
|
||||
|
@ -2835,6 +2919,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
|||
goto end;
|
||||
}
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode);
|
||||
|
||||
ath5k_hw_set_lladdr(sc->ah, vif->addr);
|
||||
ath5k_mode_setup(sc);
|
||||
|
||||
|
@ -2905,7 +2991,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
|
|||
* then we must allow the user to set how many tx antennas we
|
||||
* have available
|
||||
*/
|
||||
ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
|
||||
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&sc->lock);
|
||||
|
|
|
@ -105,6 +105,24 @@ struct ath5k_rfkill {
|
|||
struct tasklet_struct toggleq;
|
||||
};
|
||||
|
||||
/* statistics (only used for debugging now) */
|
||||
struct ath5k_statistics {
|
||||
unsigned int antenna_rx[5]; /* frames count per antenna RX */
|
||||
unsigned int antenna_tx[5]; /* frames count per antenna TX */
|
||||
unsigned int rx_all_count; /* all RX frames, including errors */
|
||||
unsigned int tx_all_count; /* all TX frames, including errors */
|
||||
unsigned int rxerr_crc;
|
||||
unsigned int rxerr_phy;
|
||||
unsigned int rxerr_fifo;
|
||||
unsigned int rxerr_decrypt;
|
||||
unsigned int rxerr_mic;
|
||||
unsigned int rxerr_proc;
|
||||
unsigned int rxerr_jumbo;
|
||||
unsigned int txerr_retry;
|
||||
unsigned int txerr_fifo;
|
||||
unsigned int txerr_filt;
|
||||
};
|
||||
|
||||
#if CHAN_DEBUG
|
||||
#define ATH_CHAN_MAX (26+26+26+200+200)
|
||||
#else
|
||||
|
@ -191,6 +209,8 @@ struct ath5k_softc {
|
|||
int power_level; /* Requested tx power in dbm */
|
||||
bool assoc; /* associate state */
|
||||
bool enable_beacon; /* true if beacons are on */
|
||||
|
||||
struct ath5k_statistics stats;
|
||||
};
|
||||
|
||||
#define ath5k_hw_hasbssidmask(_ah) \
|
||||
|
|
|
@ -102,9 +102,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
|
|||
}
|
||||
}
|
||||
|
||||
/* GPIO */
|
||||
ah->ah_gpio_npins = AR5K_NUM_GPIO;
|
||||
|
||||
/* Set number of supported TX queues */
|
||||
if (ah->ah_version == AR5K_AR5210)
|
||||
ah->ah_capabilities.cap_queues.q_tx_num =
|
||||
|
|
|
@ -364,6 +364,207 @@ static const struct file_operations fops_debug = {
|
|||
};
|
||||
|
||||
|
||||
/* debugfs: antenna */
|
||||
|
||||
static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
char buf[700];
|
||||
unsigned int len = 0;
|
||||
unsigned int i;
|
||||
unsigned int v;
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
|
||||
sc->ah->ah_ant_mode);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
|
||||
sc->ah->ah_def_ant);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
|
||||
sc->ah->ah_tx_ant);
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n");
|
||||
for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"[antenna %d]\t%d\t%d\n",
|
||||
i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
|
||||
}
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
|
||||
sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);
|
||||
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
|
||||
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
|
||||
(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
|
||||
(v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
|
||||
(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
|
||||
(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
|
||||
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
|
||||
(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
|
||||
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
|
||||
(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
|
||||
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
|
||||
(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_antenna(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
unsigned int i;
|
||||
char buf[20];
|
||||
|
||||
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
|
||||
return -EFAULT;
|
||||
|
||||
if (strncmp(buf, "diversity", 9) == 0) {
|
||||
ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
|
||||
printk(KERN_INFO "ath5k debug: enable diversity\n");
|
||||
} else if (strncmp(buf, "fixed-a", 7) == 0) {
|
||||
ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
|
||||
printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
|
||||
} else if (strncmp(buf, "fixed-b", 7) == 0) {
|
||||
ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
|
||||
printk(KERN_INFO "ath5k debug: fixed antenna B\n");
|
||||
} else if (strncmp(buf, "clear", 5) == 0) {
|
||||
for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
|
||||
sc->stats.antenna_rx[i] = 0;
|
||||
sc->stats.antenna_tx[i] = 0;
|
||||
}
|
||||
printk(KERN_INFO "ath5k debug: cleared antenna stats\n");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_antenna = {
|
||||
.read = read_file_antenna,
|
||||
.write = write_file_antenna,
|
||||
.open = ath5k_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
/* debugfs: frameerrors */
|
||||
|
||||
static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
struct ath5k_statistics *st = &sc->stats;
|
||||
char buf[700];
|
||||
unsigned int len = 0;
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"RX\n---------------------\n");
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n",
|
||||
st->rxerr_crc,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_crc*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n",
|
||||
st->rxerr_phy,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_phy*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
|
||||
st->rxerr_fifo,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_fifo*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n",
|
||||
st->rxerr_decrypt,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_decrypt*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n",
|
||||
st->rxerr_mic,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_mic*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n",
|
||||
st->rxerr_proc,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_proc*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n",
|
||||
st->rxerr_jumbo,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_jumbo*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
|
||||
st->rx_all_count);
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"\nTX\n---------------------\n");
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n",
|
||||
st->txerr_retry,
|
||||
st->tx_all_count > 0 ?
|
||||
st->txerr_retry*100/st->tx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
|
||||
st->txerr_fifo,
|
||||
st->tx_all_count > 0 ?
|
||||
st->txerr_fifo*100/st->tx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n",
|
||||
st->txerr_filt,
|
||||
st->tx_all_count > 0 ?
|
||||
st->txerr_filt*100/st->tx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
|
||||
st->tx_all_count);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_frameerrors(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
struct ath5k_statistics *st = &sc->stats;
|
||||
char buf[20];
|
||||
|
||||
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
|
||||
return -EFAULT;
|
||||
|
||||
if (strncmp(buf, "clear", 5) == 0) {
|
||||
st->rxerr_crc = 0;
|
||||
st->rxerr_phy = 0;
|
||||
st->rxerr_fifo = 0;
|
||||
st->rxerr_decrypt = 0;
|
||||
st->rxerr_mic = 0;
|
||||
st->rxerr_proc = 0;
|
||||
st->rxerr_jumbo = 0;
|
||||
st->rx_all_count = 0;
|
||||
st->txerr_retry = 0;
|
||||
st->txerr_fifo = 0;
|
||||
st->txerr_filt = 0;
|
||||
st->tx_all_count = 0;
|
||||
printk(KERN_INFO "ath5k debug: cleared frameerrors stats\n");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_frameerrors = {
|
||||
.read = read_file_frameerrors,
|
||||
.write = write_file_frameerrors,
|
||||
.open = ath5k_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
/* init */
|
||||
|
||||
void
|
||||
|
@ -393,6 +594,15 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
|
|||
|
||||
sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_reset);
|
||||
|
||||
sc->debug.debugfs_antenna = debugfs_create_file("antenna",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_antenna);
|
||||
|
||||
sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
&fops_frameerrors);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -408,6 +618,8 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
|
|||
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_frameerrors);
|
||||
debugfs_remove(sc->debug.debugfs_phydir);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ struct ath5k_dbg_info {
|
|||
struct dentry *debugfs_registers;
|
||||
struct dentry *debugfs_beacon;
|
||||
struct dentry *debugfs_reset;
|
||||
struct dentry *debugfs_antenna;
|
||||
struct dentry *debugfs_frameerrors;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
*/
|
||||
static int
|
||||
ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
||||
unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
|
||||
unsigned int pkt_len, unsigned int hdr_len, int padsize,
|
||||
enum ath5k_pkt_type type,
|
||||
unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
|
||||
unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
|
||||
unsigned int rtscts_rate, unsigned int rtscts_duration)
|
||||
|
@ -71,7 +72,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|||
/* Verify and set frame length */
|
||||
|
||||
/* remove padding we might have added before */
|
||||
frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
|
||||
frame_len = pkt_len - padsize + FCS_LEN;
|
||||
|
||||
if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
|
||||
return -EINVAL;
|
||||
|
@ -100,7 +101,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|||
AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
|
||||
}
|
||||
|
||||
/*Diferences between 5210-5211*/
|
||||
/*Differences between 5210-5211*/
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
switch (type) {
|
||||
case AR5K_PKT_TYPE_BEACON:
|
||||
|
@ -165,6 +166,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|||
*/
|
||||
static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
|
||||
int padsize,
|
||||
enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
|
||||
unsigned int tx_tries0, unsigned int key_index,
|
||||
unsigned int antenna_mode, unsigned int flags,
|
||||
|
@ -206,7 +208,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
|||
/* Verify and set frame length */
|
||||
|
||||
/* remove padding we might have added before */
|
||||
frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
|
||||
frame_len = pkt_len - padsize + FCS_LEN;
|
||||
|
||||
if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
|
||||
return -EINVAL;
|
||||
|
@ -229,7 +231,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
|||
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_TUNE_HWTXTRIES,
|
||||
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;
|
||||
|
||||
|
@ -668,12 +670,6 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
|
|||
ah->ah_version != AR5K_AR5212)
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* XXX: What is this magic value and where is it used ? */
|
||||
if (ah->ah_version == AR5K_AR5212)
|
||||
ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
|
||||
else if (ah->ah_version == AR5K_AR5211)
|
||||
ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
|
||||
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
|
||||
ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
|
||||
|
|
|
@ -329,7 +329,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
|
|||
ee->ee_x_gain[mode] = (val >> 1) & 0xf;
|
||||
ee->ee_xpd[mode] = val & 0x1;
|
||||
|
||||
if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
|
||||
if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
|
||||
mode != AR5K_EEPROM_MODE_11B)
|
||||
ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
|
||||
|
||||
if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
|
||||
|
@ -339,6 +340,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
|
|||
if (mode == AR5K_EEPROM_MODE_11A)
|
||||
ee->ee_xr_power[mode] = val & 0x3f;
|
||||
else {
|
||||
/* b_DB_11[bg] and b_OB_11[bg] */
|
||||
ee->ee_ob[mode][0] = val & 0x7;
|
||||
ee->ee_db[mode][0] = (val >> 3) & 0x7;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
* SERDES infos are present */
|
||||
#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
|
||||
#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
|
||||
#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
|
||||
#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
|
||||
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
|
||||
|
||||
#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
|
||||
|
||||
|
@ -78,9 +75,9 @@
|
|||
#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
|
||||
#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
|
||||
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
|
||||
#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz */
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for < 2W power consumption */
|
||||
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) /* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */
|
||||
#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
|
||||
#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
|
||||
|
||||
|
@ -101,7 +98,7 @@
|
|||
|
||||
#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
|
||||
#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
|
||||
#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
|
||||
#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) /* has 32KHz crystal for sleep mode */
|
||||
#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1)
|
||||
|
||||
#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6)
|
||||
|
@ -114,26 +111,27 @@
|
|||
|
||||
#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8)
|
||||
#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff)
|
||||
#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3)
|
||||
#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3)
|
||||
#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) /* modes supported by radio 0 (bit 1: G, bit 2: A) */
|
||||
#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) /* modes supported by radio 1 (bit 1: G, bit 2: A) */
|
||||
|
||||
#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9)
|
||||
#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1)
|
||||
#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1)
|
||||
#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1)
|
||||
#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1)
|
||||
#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf)
|
||||
#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1)
|
||||
#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf)
|
||||
#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) /* disable compression */
|
||||
#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) /* disable AES */
|
||||
#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) /* disable fast frames */
|
||||
#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) /* disable bursting */
|
||||
#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) /* max number of QCUs. defaults to 10 */
|
||||
#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heayy clipping */
|
||||
#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) /* key cache size. defaults to 128 */
|
||||
|
||||
#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
|
||||
#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8)
|
||||
#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8)
|
||||
#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1)
|
||||
#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1)
|
||||
#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x7) /* MIMO chains disabled for TX bitmask */
|
||||
#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x7) /* MIMO chains disabled for RX bitmask */
|
||||
#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) /* 5.47-5.7GHz supported */
|
||||
#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) /* Japan UNII1 band (5.15-5.25GHz) on even channels (5180, 5200, 5220, 5240) supported */
|
||||
#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) /* Japan UNII2 band (5.25-5.35GHz) supported */
|
||||
#define AR5K_EEPROM_JAP_MID_EN (((_v) >> 9) & 0x1) /* Japan band from 5.47-5.7GHz supported */
|
||||
#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 10) & 0x1) /* Japan UNII2 band (5.15-5.25GHz) on odd channels (5170, 5190, 5210, 5230) supported */
|
||||
#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 11) & 0x1) /* Japan A mode enabled (using even channels) */
|
||||
|
||||
/* calibration settings */
|
||||
#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
|
||||
|
@ -389,7 +387,49 @@ struct ath5k_edge_power {
|
|||
bool flag;
|
||||
};
|
||||
|
||||
/* EEPROM calibration data */
|
||||
/**
|
||||
* struct ath5k_eeprom_info - EEPROM calibration data
|
||||
*
|
||||
* @ee_regdomain: ath/regd.c takes care of COUNTRY_ERD and WORLDWIDE_ROAMING
|
||||
* flags
|
||||
* @ee_ant_gain: Antenna gain in 0.5dB steps signed [5211 only?]
|
||||
* @ee_cck_ofdm_gain_delta: difference in gainF to output the same power for
|
||||
* OFDM and CCK packets
|
||||
* @ee_cck_ofdm_power_delta: power difference between OFDM (6Mbps) and CCK
|
||||
* (11Mbps) rate in G mode. 0.1dB steps
|
||||
* @ee_scaled_cck_delta: for Japan Channel 14: 0.1dB resolution
|
||||
*
|
||||
* @ee_i_cal: Initial I coefficient to correct I/Q mismatch in the receive path
|
||||
* @ee_q_cal: Initial Q coefficient to correct I/Q mismatch in the receive path
|
||||
* @ee_fixed_bias: use ee_ob and ee_db settings or use automatic control
|
||||
* @ee_switch_settling: RX/TX Switch settling time
|
||||
* @ee_atn_tx_rx: Difference in attenuation between TX and RX in 1dB steps
|
||||
* @ee_ant_control: Antenna Control Settings
|
||||
* @ee_ob: Bias current for Output stage of PA
|
||||
* B/G mode: Index [0] is used for AR2112/5112, otherwise [1]
|
||||
* A mode: [0] 5.15-5.25 [1] 5.25-5.50 [2] 5.50-5.70 [3] 5.70-5.85 GHz
|
||||
* @ee_db: Bias current for Output stage of PA. see @ee_ob
|
||||
* @ee_tx_end2xlna_enable: Time difference from when BB finishes sending a frame
|
||||
* to when the external LNA is activated
|
||||
* @ee_tx_end2xpa_disable: Time difference from when BB finishes sending a frame
|
||||
* to when the external PA switch is deactivated
|
||||
* @ee_tx_frm2xpa_enable: Time difference from when MAC sends frame to when
|
||||
* external PA switch is activated
|
||||
* @ee_thr_62: Clear Channel Assessment (CCA) sensitivity
|
||||
* (IEEE802.11a section 17.3.10.5 )
|
||||
* @ee_xlna_gain: Total gain of the LNA (information only)
|
||||
* @ee_xpd: Use external (1) or internal power detector
|
||||
* @ee_x_gain: Gain for external power detector output (differences in EEMAP
|
||||
* versions!)
|
||||
* @ee_i_gain: Initial gain value after reset
|
||||
* @ee_margin_tx_rx: Margin in dB when final attenuation stage should be used
|
||||
*
|
||||
* @ee_false_detect: Backoff in Sensitivity (dB) on channels with spur signals
|
||||
* @ee_noise_floor_thr: Noise floor threshold in 1dB steps
|
||||
* @ee_adc_desired_size: Desired amplitude for ADC, used by AGC; in 0.5 dB steps
|
||||
* @ee_pga_desired_size: Desired output of PGA (for BB gain) in 0.5 dB steps
|
||||
* @ee_pd_gain_overlap: PD ADC curves need to overlap in 0.5dB steps (ee_map>=2)
|
||||
*/
|
||||
struct ath5k_eeprom_info {
|
||||
|
||||
/* Header information */
|
||||
|
|
|
@ -39,16 +39,16 @@
|
|||
* ath5k_hw_set_opmode - Set PCU operating mode
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @op_mode: &enum nl80211_iftype operating mode
|
||||
*
|
||||
* Initialize PCU for the various operating modes (AP/STA etc)
|
||||
*
|
||||
* NOTE: ah->ah_op_mode must be set before calling this.
|
||||
*/
|
||||
int ath5k_hw_set_opmode(struct ath5k_hw *ah)
|
||||
int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
u32 pcu_reg, beacon_reg, low_id, high_id;
|
||||
|
||||
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
|
||||
|
||||
/* Preserve rest settings */
|
||||
pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
|
||||
|
@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
|
|||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
switch (ah->ah_op_mode) {
|
||||
switch (op_mode) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
|
||||
beacon_reg |= AR5K_BCR_ADHOC;
|
||||
|
@ -178,26 +178,13 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
|
|||
* ACK/CTS Timeouts *
|
||||
\******************/
|
||||
|
||||
/**
|
||||
* ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
*/
|
||||
unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
|
||||
AR5K_TIME_OUT), AR5K_TIME_OUT_ACK));
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @timeout: Timeout in usec
|
||||
*/
|
||||
int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
|
||||
|
@ -210,25 +197,13 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
*/
|
||||
unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
|
||||
AR5K_TIME_OUT), AR5K_TIME_OUT_CTS));
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @timeout: Timeout in usec
|
||||
*/
|
||||
int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
|
||||
|
@ -290,7 +265,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
|
|||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
*/
|
||||
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
|
||||
static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ieee80211_channel *channel = ah->ah_current_channel;
|
||||
|
||||
|
@ -308,7 +283,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
|
|||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
*/
|
||||
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
|
||||
static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ieee80211_channel *channel = ah->ah_current_channel;
|
||||
|
||||
|
@ -451,42 +426,6 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
|
|||
ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set multicast filter by index
|
||||
*/
|
||||
int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
|
||||
{
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (index >= 64)
|
||||
return -EINVAL;
|
||||
else if (index >= 32)
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
|
||||
(1 << (index - 32)));
|
||||
else
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear Multicast filter by index
|
||||
*/
|
||||
int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
|
||||
{
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (index >= 64)
|
||||
return -EINVAL;
|
||||
else if (index >= 32)
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
|
||||
(1 << (index - 32)));
|
||||
else
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_get_rx_filter - Get current rx filter
|
||||
*
|
||||
|
@ -571,19 +510,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
|
|||
* Beacon control *
|
||||
\****************/
|
||||
|
||||
/**
|
||||
* ath5k_hw_get_tsf32 - Get a 32bit TSF
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
*
|
||||
* Returns lower 32 bits of current TSF
|
||||
*/
|
||||
u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_get_tsf64 - Get the full 64bit TSF
|
||||
*
|
||||
|
@ -651,7 +577,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|||
/*
|
||||
* Set the additional timers by mode
|
||||
*/
|
||||
switch (ah->ah_op_mode) {
|
||||
switch (ah->ah_sc->opmode) {
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
/* In STA mode timer1 is used as next wakeup
|
||||
|
@ -688,8 +614,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|||
* Set the beacon register and enable all timers.
|
||||
*/
|
||||
/* When in AP or Mesh Point mode zero timer0 to start TSF */
|
||||
if (ah->ah_op_mode == NL80211_IFTYPE_AP ||
|
||||
ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT)
|
||||
if (ah->ah_sc->opmode == NL80211_IFTYPE_AP ||
|
||||
ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT)
|
||||
ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
|
||||
|
||||
ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
|
||||
|
@ -722,203 +648,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Set beacon timers
|
||||
*/
|
||||
int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
|
||||
const struct ath5k_beacon_state *state)
|
||||
{
|
||||
u32 cfp_period, next_cfp, dtim, interval, next_beacon;
|
||||
|
||||
/*
|
||||
* TODO: should be changed through *state
|
||||
* review struct ath5k_beacon_state struct
|
||||
*
|
||||
* XXX: These are used for cfp period bellow, are they
|
||||
* ok ? Is it O.K. for tsf here to be 0 or should we use
|
||||
* get_tsf ?
|
||||
*/
|
||||
u32 dtim_count = 0; /* XXX */
|
||||
u32 cfp_count = 0; /* XXX */
|
||||
u32 tsf = 0; /* XXX */
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/* Return on an invalid beacon state */
|
||||
if (state->bs_interval < 1)
|
||||
return -EINVAL;
|
||||
|
||||
interval = state->bs_interval;
|
||||
dtim = state->bs_dtim_period;
|
||||
|
||||
/*
|
||||
* PCF support?
|
||||
*/
|
||||
if (state->bs_cfp_period > 0) {
|
||||
/*
|
||||
* Enable PCF mode and set the CFP
|
||||
* (Contention Free Period) and timer registers
|
||||
*/
|
||||
cfp_period = state->bs_cfp_period * state->bs_dtim_period *
|
||||
state->bs_interval;
|
||||
next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
|
||||
state->bs_interval;
|
||||
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
|
||||
AR5K_STA_ID1_DEFAULT_ANTENNA |
|
||||
AR5K_STA_ID1_PCF);
|
||||
ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
|
||||
ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
|
||||
AR5K_CFP_DUR);
|
||||
ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
|
||||
next_cfp)) << 3, AR5K_TIMER2);
|
||||
} else {
|
||||
/* Disable PCF mode */
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
|
||||
AR5K_STA_ID1_DEFAULT_ANTENNA |
|
||||
AR5K_STA_ID1_PCF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the beacon timer register
|
||||
*/
|
||||
ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
|
||||
|
||||
/*
|
||||
* Start the beacon timers
|
||||
*/
|
||||
ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &
|
||||
~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
|
||||
AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
|
||||
AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
|
||||
AR5K_BEACON_PERIOD), AR5K_BEACON);
|
||||
|
||||
/*
|
||||
* Write new beacon miss threshold, if it appears to be valid
|
||||
* XXX: Figure out right values for min <= bs_bmiss_threshold <= max
|
||||
* and return if its not in range. We can test this by reading value and
|
||||
* setting value to a largest value and seeing which values register.
|
||||
*/
|
||||
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
|
||||
state->bs_bmiss_threshold);
|
||||
|
||||
/*
|
||||
* Set sleep control register
|
||||
* XXX: Didn't find this in 5210 code but since this register
|
||||
* exists also in ar5k's 5210 headers i leave it as common code.
|
||||
*/
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
|
||||
(state->bs_sleep_duration - 3) << 3);
|
||||
|
||||
/*
|
||||
* Set enhanced sleep registers on 5212
|
||||
*/
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
if (state->bs_sleep_duration > state->bs_interval &&
|
||||
roundup(state->bs_sleep_duration, interval) ==
|
||||
state->bs_sleep_duration)
|
||||
interval = state->bs_sleep_duration;
|
||||
|
||||
if (state->bs_sleep_duration > dtim && (dtim == 0 ||
|
||||
roundup(state->bs_sleep_duration, dtim) ==
|
||||
state->bs_sleep_duration))
|
||||
dtim = state->bs_sleep_duration;
|
||||
|
||||
if (interval > dtim)
|
||||
return -EINVAL;
|
||||
|
||||
next_beacon = interval == dtim ? state->bs_next_dtim :
|
||||
state->bs_next_beacon;
|
||||
|
||||
ath5k_hw_reg_write(ah,
|
||||
AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
|
||||
AR5K_SLEEP0_NEXT_DTIM) |
|
||||
AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
|
||||
AR5K_SLEEP0_ENH_SLEEP_EN |
|
||||
AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
|
||||
|
||||
ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
|
||||
AR5K_SLEEP1_NEXT_TIM) |
|
||||
AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
|
||||
|
||||
ath5k_hw_reg_write(ah,
|
||||
AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
|
||||
AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset beacon timers
|
||||
*/
|
||||
void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/*
|
||||
* Disable beacon timer
|
||||
*/
|
||||
ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
|
||||
|
||||
/*
|
||||
* Disable some beacon register values
|
||||
*/
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
|
||||
AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
|
||||
ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for beacon queue to finish
|
||||
*/
|
||||
int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/* 5210 doesn't have QCU*/
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
/*
|
||||
* Wait for beaconn queue to finish by checking
|
||||
* Control Register and Beacon Status Register.
|
||||
*/
|
||||
for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
|
||||
if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
|
||||
||
|
||||
!(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/* Timeout... */
|
||||
if (i <= 0) {
|
||||
/*
|
||||
* Re-schedule the beacon queue
|
||||
*/
|
||||
ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
|
||||
ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
|
||||
AR5K_BCR);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
/*5211/5212*/
|
||||
ret = ath5k_hw_register_timeout(ah,
|
||||
AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
|
||||
AR5K_QCU_STS_FRMPENDCNT, 0, false);
|
||||
|
||||
if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*********************\
|
||||
* Key table functions *
|
||||
|
@ -971,19 +700,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a table entry is valid
|
||||
*/
|
||||
int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
||||
|
||||
/* Check the validation flag at the end of the entry */
|
||||
return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
|
||||
AR5K_KEYTABLE_VALID;
|
||||
}
|
||||
|
||||
static
|
||||
int ath5k_keycache_type(const struct ieee80211_key_conf *key)
|
||||
{
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define _ATH5K_PHY
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "ath5k.h"
|
||||
|
@ -1190,7 +1188,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
|
|||
* The median of the values in the history is then loaded into the
|
||||
* hardware for its own use for RSSI and CCA measurements.
|
||||
*/
|
||||
void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
u32 val;
|
||||
|
@ -1399,7 +1397,11 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
|
|||
}
|
||||
|
||||
i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
|
||||
q_coffd = q_pwr >> 7;
|
||||
|
||||
if (ah->ah_version == AR5K_AR5211)
|
||||
q_coffd = q_pwr >> 6;
|
||||
else
|
||||
q_coffd = q_pwr >> 7;
|
||||
|
||||
/* protect against divide by 0 and loss of sign bits */
|
||||
if (i_coffd == 0 || q_coffd < 2)
|
||||
|
@ -1768,7 +1770,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
|
|||
* Antenna control *
|
||||
\*****************/
|
||||
|
||||
void /*TODO:Boundary check*/
|
||||
static void /*TODO:Boundary check*/
|
||||
ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
@ -1777,16 +1779,6 @@ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
|
|||
ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
|
||||
}
|
||||
|
||||
unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (ah->ah_version != AR5K_AR5210)
|
||||
return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7;
|
||||
|
||||
return false; /*XXX: What do we return for 5210 ?*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/disable fast rx antenna diversity
|
||||
*/
|
||||
|
@ -1930,6 +1922,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
|
|||
|
||||
ah->ah_tx_ant = tx_ant;
|
||||
ah->ah_ant_mode = ant_mode;
|
||||
ah->ah_def_ant = def_ant;
|
||||
|
||||
sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0;
|
||||
sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0;
|
||||
|
@ -2440,19 +2433,6 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
|
|||
pcdac_tmp = pcdac_high_pwr;
|
||||
|
||||
edge_flag = 0x40;
|
||||
#if 0
|
||||
/* If both min and max power limits are in lower
|
||||
* power curve's range, only use the low power curve.
|
||||
* TODO: min/max levels are related to target
|
||||
* power values requested from driver/user
|
||||
* XXX: Is this really needed ? */
|
||||
if (min_pwr < table_max[1] &&
|
||||
max_pwr < table_max[1]) {
|
||||
edge_flag = 0;
|
||||
pcdac_tmp = pcdac_low_pwr;
|
||||
max_pwr_idx = (table_max[1] - table_min[1])/2;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
|
||||
pcdac_high_pwr = ah->ah_txpower.tmpL[0];
|
||||
|
@ -3143,5 +3123,3 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
|
|||
|
||||
return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
|
||||
}
|
||||
|
||||
#undef _ATH5K_PHY
|
||||
|
|
|
@ -516,23 +516,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get slot time from DCU
|
||||
*/
|
||||
unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
|
||||
{
|
||||
unsigned int slot_time_clock;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (ah->ah_version == AR5K_AR5210)
|
||||
slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME);
|
||||
else
|
||||
slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT);
|
||||
|
||||
return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set slot time on DCU
|
||||
*/
|
||||
|
|
|
@ -1974,7 +1974,7 @@
|
|||
#define AR5K_PHY_SETTLING 0x9844 /* Register Address */
|
||||
#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
|
||||
#define AR5K_PHY_SETTLING_AGC_S 0
|
||||
#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
|
||||
#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settling time */
|
||||
#define AR5K_PHY_SETTLING_SWITCH_S 7
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define _ATH5K_RESET
|
||||
|
||||
/*****************************\
|
||||
Reset functions and helpers
|
||||
\*****************************/
|
||||
|
@ -34,6 +32,27 @@
|
|||
#include "base.h"
|
||||
#include "debug.h"
|
||||
|
||||
/*
|
||||
* Check if a register write has been completed
|
||||
*/
|
||||
int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
|
||||
bool is_set)
|
||||
{
|
||||
int i;
|
||||
u32 data;
|
||||
|
||||
for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
|
||||
data = ath5k_hw_reg_read(ah, reg);
|
||||
if (is_set && (data & flag))
|
||||
break;
|
||||
else if ((data & flag) == val)
|
||||
break;
|
||||
udelay(15);
|
||||
}
|
||||
|
||||
return (i <= 0) ? -EAGAIN : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
|
||||
*
|
||||
|
@ -221,8 +240,8 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
|
|||
/*
|
||||
* Sleep control
|
||||
*/
|
||||
int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
||||
bool set_chip, u16 sleep_duration)
|
||||
static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
||||
bool set_chip, u16 sleep_duration)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 staid, data;
|
||||
|
@ -1017,11 +1036,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Initialize operating mode
|
||||
*/
|
||||
ah->ah_op_mode = op_mode;
|
||||
|
||||
/* PHY access enable */
|
||||
if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
|
||||
ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
|
||||
|
@ -1192,7 +1206,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
ath5k_hw_set_associd(ah);
|
||||
|
||||
/* Set PCU config */
|
||||
ath5k_hw_set_opmode(ah);
|
||||
ath5k_hw_set_opmode(ah, op_mode);
|
||||
|
||||
/* Clear any pending interrupts
|
||||
* PISR/SISR Not available on 5210 */
|
||||
|
@ -1378,7 +1392,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
* external 32KHz crystal when sleeping if one
|
||||
* exists */
|
||||
if (ah->ah_version == AR5K_AR5212 &&
|
||||
ah->ah_op_mode != NL80211_IFTYPE_AP)
|
||||
op_mode != NL80211_IFTYPE_AP)
|
||||
ath5k_hw_set_sleep_clock(ah, true);
|
||||
|
||||
/*
|
||||
|
@ -1388,5 +1402,3 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
ath5k_hw_reset_tsf(ah);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef _ATH5K_RESET
|
||||
|
|
|
@ -1151,7 +1151,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
|
|||
ah->mask_reg |= AR_IMR_MIB;
|
||||
|
||||
REG_WRITE(ah, AR_IMR, ah->mask_reg);
|
||||
REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
|
||||
ah->imrs2_reg |= AR_IMR_S2_GTT;
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
|
||||
|
@ -2920,14 +2921,11 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
|
|||
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
|
||||
REG_WRITE(ah, AR_IMR, mask);
|
||||
mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
|
||||
AR_IMR_S2_DTIM |
|
||||
AR_IMR_S2_DTIMSYNC |
|
||||
AR_IMR_S2_CABEND |
|
||||
AR_IMR_S2_CABTO |
|
||||
AR_IMR_S2_TSFOOR |
|
||||
AR_IMR_S2_GTT | AR_IMR_S2_CST);
|
||||
REG_WRITE(ah, AR_IMR_S2, mask | mask2);
|
||||
ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
|
||||
AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
|
||||
AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
|
||||
ah->imrs2_reg |= mask2;
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
ah->mask_reg = ints;
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
|
||||
|
|
|
@ -479,6 +479,7 @@ struct ath_hw {
|
|||
|
||||
int16_t curchan_rad_index;
|
||||
u32 mask_reg;
|
||||
u32 imrs2_reg;
|
||||
u32 txok_interrupt_mask;
|
||||
u32 txerr_interrupt_mask;
|
||||
u32 txdesc_interrupt_mask;
|
||||
|
|
|
@ -31,8 +31,10 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
|
|||
REG_WRITE(ah, AR_IMR_S1,
|
||||
SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
|
||||
| SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
|
||||
REG_RMW_FIELD(ah, AR_IMR_S2,
|
||||
AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask);
|
||||
|
||||
ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
|
||||
ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
}
|
||||
|
||||
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
|
||||
|
|
|
@ -1226,8 +1226,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
|||
long_retry = rate->count - 1;
|
||||
}
|
||||
|
||||
if (!priv_sta || !ieee80211_is_data(fc) ||
|
||||
!(tx_info->pad[0] & ATH_TX_INFO_UPDATE_RC))
|
||||
if (!priv_sta || !ieee80211_is_data(fc))
|
||||
return;
|
||||
|
||||
/* This packet was aggregated but doesn't carry status info */
|
||||
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
!(tx_info->flags & IEEE80211_TX_STAT_AMPDU))
|
||||
return;
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
|
||||
|
|
|
@ -172,7 +172,6 @@ struct ath_rate_priv {
|
|||
|
||||
#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0)
|
||||
#define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1)
|
||||
#define ATH_TX_INFO_UPDATE_RC (1 << 2)
|
||||
#define ATH_TX_INFO_XRETRY (1 << 3)
|
||||
#define ATH_TX_INFO_UNDERRUN (1 << 4)
|
||||
|
||||
|
|
|
@ -1928,10 +1928,10 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
|
|||
tx_rateindex = ds->ds_txstat.ts_rateindex;
|
||||
WARN_ON(tx_rateindex >= hw->max_rates);
|
||||
|
||||
if (update_rc)
|
||||
tx_info->pad[0] |= ATH_TX_INFO_UPDATE_RC;
|
||||
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
|
||||
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
|
||||
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
|
||||
if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
|
||||
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
#define B43_MMIO_MACFILTER_CONTROL 0x420
|
||||
#define B43_MMIO_MACFILTER_DATA 0x422
|
||||
#define B43_MMIO_RCMTA_COUNT 0x43C
|
||||
#define B43_MMIO_PSM_PHY_HDR 0x492
|
||||
#define B43_MMIO_RADIO_HWENABLED_LO 0x49A
|
||||
#define B43_MMIO_GPIO_CONTROL 0x49C
|
||||
#define B43_MMIO_GPIO_MASK 0x49E
|
||||
|
|
|
@ -72,6 +72,22 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
|
|||
u16 value, u8 core, bool off);
|
||||
static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
|
||||
u16 value, u8 core);
|
||||
static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel);
|
||||
|
||||
static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec)
|
||||
{
|
||||
return !chanspec->channel && !chanspec->sideband &&
|
||||
!chanspec->b_width && !chanspec->b_freq;
|
||||
}
|
||||
|
||||
static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1,
|
||||
struct b43_chanspec *chanspec2)
|
||||
{
|
||||
return (chanspec1->channel == chanspec2->channel &&
|
||||
chanspec1->sideband == chanspec2->sideband &&
|
||||
chanspec1->b_width == chanspec2->b_width &&
|
||||
chanspec1->b_freq == chanspec2->b_freq);
|
||||
}
|
||||
|
||||
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
|
||||
{//TODO
|
||||
|
@ -90,28 +106,38 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
|
|||
static void b43_chantab_radio_upload(struct b43_wldev *dev,
|
||||
const struct b43_nphy_channeltab_entry *e)
|
||||
{
|
||||
b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref);
|
||||
b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
|
||||
b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
|
||||
b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
|
||||
b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
|
||||
b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
|
||||
b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
|
||||
b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
|
||||
b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
|
||||
b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
|
||||
b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
|
||||
b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
|
||||
b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
|
||||
b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
|
||||
b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
|
||||
b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
|
||||
b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
|
||||
b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
|
||||
b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
|
||||
b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
|
||||
b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
|
||||
b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
|
||||
b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
|
||||
b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
|
||||
b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
|
||||
b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
|
||||
|
||||
b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
|
||||
b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
|
||||
b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
|
||||
b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
|
||||
|
||||
b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
|
||||
b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
|
||||
b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
|
||||
b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
|
||||
|
||||
b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
|
||||
b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
|
||||
b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
|
||||
b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
|
||||
|
||||
b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
|
||||
b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
|
||||
b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
|
||||
b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
|
||||
|
||||
b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
|
||||
b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
|
||||
}
|
||||
|
||||
static void b43_chantab_phy_upload(struct b43_wldev *dev,
|
||||
|
@ -130,34 +156,20 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
|
|||
//TODO
|
||||
}
|
||||
|
||||
/* Tune the hardware to a new channel. */
|
||||
static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
|
||||
static void b43_radio_2055_setup(struct b43_wldev *dev,
|
||||
const struct b43_nphy_channeltab_entry *e)
|
||||
{
|
||||
const struct b43_nphy_channeltab_entry *tabent;
|
||||
B43_WARN_ON(dev->phy.rev >= 3);
|
||||
|
||||
tabent = b43_nphy_get_chantabent(dev, channel);
|
||||
if (!tabent)
|
||||
return -ESRCH;
|
||||
|
||||
//FIXME enable/disable band select upper20 in RXCTL
|
||||
if (0 /*FIXME 5Ghz*/)
|
||||
b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20);
|
||||
else
|
||||
b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50);
|
||||
b43_chantab_radio_upload(dev, tabent);
|
||||
b43_chantab_radio_upload(dev, e);
|
||||
udelay(50);
|
||||
b43_radio_write16(dev, B2055_VCO_CAL10, 5);
|
||||
b43_radio_write16(dev, B2055_VCO_CAL10, 45);
|
||||
b43_radio_write16(dev, B2055_VCO_CAL10, 65);
|
||||
b43_radio_write(dev, B2055_VCO_CAL10, 5);
|
||||
b43_radio_write(dev, B2055_VCO_CAL10, 45);
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
|
||||
b43_radio_write(dev, B2055_VCO_CAL10, 65);
|
||||
udelay(300);
|
||||
if (0 /*FIXME 5Ghz*/)
|
||||
b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
|
||||
else
|
||||
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
|
||||
b43_chantab_phy_upload(dev, tabent);
|
||||
b43_nphy_tx_power_fix(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void b43_radio_init2055_pre(struct b43_wldev *dev)
|
||||
|
@ -173,52 +185,64 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev)
|
|||
|
||||
static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
|
||||
struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo);
|
||||
int i;
|
||||
u16 val;
|
||||
bool workaround = false;
|
||||
|
||||
if (sprom->revision < 4)
|
||||
workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM ||
|
||||
binfo->type != 0x46D ||
|
||||
binfo->rev < 0x41);
|
||||
else
|
||||
workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0);
|
||||
|
||||
b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
|
||||
msleep(1);
|
||||
if ((sprom->revision != 4) ||
|
||||
!(sprom->boardflags_hi & B43_BFH_RSSIINV)) {
|
||||
if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) ||
|
||||
(binfo->type != 0x46D) ||
|
||||
(binfo->rev < 0x41)) {
|
||||
b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
|
||||
b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
|
||||
msleep(1);
|
||||
}
|
||||
if (workaround) {
|
||||
b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
|
||||
b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
|
||||
}
|
||||
b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C);
|
||||
msleep(1);
|
||||
b43_radio_write16(dev, B2055_CAL_MISC, 0x3C);
|
||||
msleep(1);
|
||||
b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
|
||||
b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
|
||||
b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
|
||||
msleep(1);
|
||||
b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
|
||||
msleep(1);
|
||||
b43_radio_set(dev, B2055_CAL_MISC, 0x1);
|
||||
msleep(1);
|
||||
b43_radio_set(dev, B2055_CAL_MISC, 0x40);
|
||||
msleep(1);
|
||||
for (i = 0; i < 100; i++) {
|
||||
val = b43_radio_read16(dev, B2055_CAL_COUT2);
|
||||
if (val & 0x80)
|
||||
for (i = 0; i < 200; i++) {
|
||||
val = b43_radio_read(dev, B2055_CAL_COUT2);
|
||||
if (val & 0x80) {
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
udelay(10);
|
||||
}
|
||||
msleep(1);
|
||||
if (i)
|
||||
b43err(dev->wl, "radio post init timeout\n");
|
||||
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
|
||||
msleep(1);
|
||||
nphy_channel_switch(dev, dev->phy.channel);
|
||||
b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9);
|
||||
b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9);
|
||||
b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
|
||||
b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
|
||||
b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
|
||||
b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
|
||||
b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
|
||||
b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
|
||||
b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
|
||||
b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
|
||||
if (!nphy->gain_boost) {
|
||||
b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
|
||||
b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
|
||||
} else {
|
||||
b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
|
||||
b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
|
||||
}
|
||||
udelay(2);
|
||||
}
|
||||
|
||||
/* Initialize a Broadcom 2055 N-radio */
|
||||
/*
|
||||
* Initialize a Broadcom 2055 N-radio
|
||||
* http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
|
||||
*/
|
||||
static void b43_radio_init2055(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_init2055_pre(dev);
|
||||
|
@ -229,17 +253,6 @@ static void b43_radio_init2055(struct b43_wldev *dev)
|
|||
b43_radio_init2055_post(dev);
|
||||
}
|
||||
|
||||
void b43_nphy_radio_turn_on(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_init2055(dev);
|
||||
}
|
||||
|
||||
void b43_nphy_radio_turn_off(struct b43_wldev *dev)
|
||||
{
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
|
||||
~B43_NPHY_RFCTL_CMD_EN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upload the N-PHY tables.
|
||||
* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
|
||||
|
@ -646,6 +659,41 @@ static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
|
|||
clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
|
||||
static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
|
||||
{
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (!init)
|
||||
return;
|
||||
if (0 /* FIXME */) {
|
||||
b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
|
||||
b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
|
||||
b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
|
||||
b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
|
||||
}
|
||||
} else {
|
||||
b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
|
||||
b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
|
||||
|
||||
ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00,
|
||||
0xFC00);
|
||||
b43_write32(dev, B43_MMIO_MACCTL,
|
||||
b43_read32(dev, B43_MMIO_MACCTL) &
|
||||
~B43_MACCTL_GPOUTSMSK);
|
||||
b43_write16(dev, B43_MMIO_GPIO_MASK,
|
||||
b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
|
||||
b43_write16(dev, B43_MMIO_GPIO_CONTROL,
|
||||
b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
|
||||
|
||||
if (init) {
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
|
||||
static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
|
||||
{
|
||||
|
@ -722,7 +770,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
|
|||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
unsigned int channel;
|
||||
u8 channel = nphy->radio_chanspec.channel;
|
||||
int tone[2] = { 57, 58 };
|
||||
u32 noise[2] = { 0x3FF, 0x3FF };
|
||||
|
||||
|
@ -731,8 +779,6 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
|
|||
if (nphy->hang_avoid)
|
||||
b43_nphy_stay_in_carrier_search(dev, 1);
|
||||
|
||||
/* FIXME: channel = radio_chanspec */
|
||||
|
||||
if (nphy->gband_spurwar_en) {
|
||||
/* TODO: N PHY Adjust Analog Pfbw (7) */
|
||||
if (channel == 11 && dev->phy.is_40mhz)
|
||||
|
@ -778,6 +824,62 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
|
|||
b43_nphy_stay_in_carrier_search(dev, 0);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
|
||||
static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
u8 i;
|
||||
s16 tmp;
|
||||
u16 data[4];
|
||||
s16 gain[2];
|
||||
u16 minmax[2];
|
||||
u16 lna_gain[4] = { -2, 10, 19, 25 };
|
||||
|
||||
if (nphy->hang_avoid)
|
||||
b43_nphy_stay_in_carrier_search(dev, 1);
|
||||
|
||||
if (nphy->gain_boost) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
gain[0] = 6;
|
||||
gain[1] = 6;
|
||||
} else {
|
||||
tmp = 40370 - 315 * nphy->radio_chanspec.channel;
|
||||
gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
|
||||
tmp = 23242 - 224 * nphy->radio_chanspec.channel;
|
||||
gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
|
||||
}
|
||||
} else {
|
||||
gain[0] = 0;
|
||||
gain[1] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (nphy->elna_gain_config) {
|
||||
data[0] = 19 + gain[i];
|
||||
data[1] = 25 + gain[i];
|
||||
data[2] = 25 + gain[i];
|
||||
data[3] = 25 + gain[i];
|
||||
} else {
|
||||
data[0] = lna_gain[0] + gain[i];
|
||||
data[1] = lna_gain[1] + gain[i];
|
||||
data[2] = lna_gain[2] + gain[i];
|
||||
data[3] = lna_gain[3] + gain[i];
|
||||
}
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data);
|
||||
|
||||
minmax[i] = 23 + gain[i];
|
||||
}
|
||||
|
||||
b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
|
||||
minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
|
||||
b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
|
||||
minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
|
||||
|
||||
if (nphy->hang_avoid)
|
||||
b43_nphy_stay_in_carrier_search(dev, 0);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
|
||||
static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
|
||||
{
|
||||
|
@ -862,7 +964,7 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
|
|||
b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
|
||||
(code << 8 | 0x7C));
|
||||
|
||||
/* TODO: b43_nphy_adjust_lna_gain_table(dev); */
|
||||
b43_nphy_adjust_lna_gain_table(dev);
|
||||
|
||||
if (nphy->elna_gain_config) {
|
||||
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
|
||||
|
@ -1969,12 +2071,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
|
|||
u16 *rssical_phy_regs = NULL;
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (!nphy->rssical_chanspec_2G)
|
||||
if (b43_empty_chanspec(&nphy->rssical_chanspec_2G))
|
||||
return;
|
||||
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
|
||||
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
|
||||
} else {
|
||||
if (!nphy->rssical_chanspec_5G)
|
||||
if (b43_empty_chanspec(&nphy->rssical_chanspec_5G))
|
||||
return;
|
||||
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
|
||||
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
|
||||
|
@ -2394,7 +2496,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
|
|||
|
||||
struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
|
||||
u16 *txcal_radio_regs = NULL;
|
||||
u8 *iqcal_chanspec;
|
||||
struct b43_chanspec *iqcal_chanspec;
|
||||
u16 *table = NULL;
|
||||
|
||||
if (nphy->hang_avoid)
|
||||
|
@ -2450,12 +2552,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
|
|||
struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (nphy->iqcal_chanspec_2G == 0)
|
||||
if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G))
|
||||
return;
|
||||
table = nphy->cal_cache.txcal_coeffs_2G;
|
||||
loft = &nphy->cal_cache.txcal_coeffs_2G[5];
|
||||
} else {
|
||||
if (nphy->iqcal_chanspec_5G == 0)
|
||||
if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G))
|
||||
return;
|
||||
table = nphy->cal_cache.txcal_coeffs_5G;
|
||||
loft = &nphy->cal_cache.txcal_coeffs_5G[5];
|
||||
|
@ -2700,8 +2802,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
|
|||
b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
|
||||
nphy->txiqlocal_bestc);
|
||||
nphy->txiqlocal_coeffsvalid = true;
|
||||
/* TODO: Set nphy->txiqlocal_chanspec to
|
||||
the current channel */
|
||||
nphy->txiqlocal_chanspec = nphy->radio_chanspec;
|
||||
} else {
|
||||
length = 11;
|
||||
if (dev->phy.rev < 3)
|
||||
|
@ -2736,7 +2837,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
|
|||
u16 buffer[7];
|
||||
bool equal = true;
|
||||
|
||||
if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */)
|
||||
if (!nphy->txiqlocal_coeffsvalid ||
|
||||
b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec))
|
||||
return;
|
||||
|
||||
b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
|
||||
|
@ -3091,9 +3193,11 @@ int b43_phy_initn(struct b43_wldev *dev)
|
|||
do_rssi_cal = false;
|
||||
if (phy->rev >= 3) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
do_rssi_cal = (nphy->rssical_chanspec_2G == 0);
|
||||
do_rssi_cal =
|
||||
b43_empty_chanspec(&nphy->rssical_chanspec_2G);
|
||||
else
|
||||
do_rssi_cal = (nphy->rssical_chanspec_5G == 0);
|
||||
do_rssi_cal =
|
||||
b43_empty_chanspec(&nphy->rssical_chanspec_5G);
|
||||
|
||||
if (do_rssi_cal)
|
||||
b43_nphy_rssi_cal(dev);
|
||||
|
@ -3105,9 +3209,9 @@ int b43_phy_initn(struct b43_wldev *dev)
|
|||
|
||||
if (!((nphy->measure_hold & 0x6) != 0)) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
do_cal = (nphy->iqcal_chanspec_2G == 0);
|
||||
do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G);
|
||||
else
|
||||
do_cal = (nphy->iqcal_chanspec_5G == 0);
|
||||
do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G);
|
||||
|
||||
if (nphy->mute)
|
||||
do_cal = false;
|
||||
|
@ -3116,7 +3220,7 @@ int b43_phy_initn(struct b43_wldev *dev)
|
|||
target = b43_nphy_get_tx_gains(dev);
|
||||
|
||||
if (nphy->antsel_type == 2)
|
||||
;/*TODO NPHY Superswitch Init with argument 1*/
|
||||
b43_nphy_superswitch_init(dev, true);
|
||||
if (nphy->perical != 2) {
|
||||
b43_nphy_rssi_cal(dev);
|
||||
if (phy->rev >= 3) {
|
||||
|
@ -3154,6 +3258,129 @@ int b43_phy_initn(struct b43_wldev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
|
||||
static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
|
||||
const struct b43_nphy_channeltab_entry *e,
|
||||
struct b43_chanspec chanspec)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
u16 tmp;
|
||||
u32 tmp32;
|
||||
|
||||
tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
|
||||
if (chanspec.b_freq == 1 && tmp == 0) {
|
||||
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
|
||||
b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
|
||||
b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
|
||||
} else if (chanspec.b_freq == 1) {
|
||||
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
|
||||
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
|
||||
b43_phy_mask(dev, B43_PHY_B_BBCFG, (u16)~0xC000);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
|
||||
}
|
||||
|
||||
b43_chantab_phy_upload(dev, e);
|
||||
|
||||
tmp = chanspec.channel;
|
||||
if (chanspec.b_freq == 1)
|
||||
tmp |= 0x0100;
|
||||
if (chanspec.b_width == 3)
|
||||
tmp |= 0x0200;
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp);
|
||||
|
||||
if (nphy->radio_chanspec.channel == 14) {
|
||||
b43_nphy_classifier(dev, 2, 0);
|
||||
b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
|
||||
} else {
|
||||
b43_nphy_classifier(dev, 2, 2);
|
||||
if (chanspec.b_freq == 2)
|
||||
b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
|
||||
}
|
||||
|
||||
if (nphy->txpwrctrl)
|
||||
b43_nphy_tx_power_fix(dev);
|
||||
|
||||
if (dev->phy.rev < 3)
|
||||
b43_nphy_adjust_lna_gain_table(dev);
|
||||
|
||||
b43_nphy_tx_lp_fbw(dev);
|
||||
|
||||
if (dev->phy.rev >= 3 && 0) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
|
||||
|
||||
if (phy->rev >= 3)
|
||||
b43_nphy_spur_workaround(dev);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
|
||||
static int b43_nphy_set_chanspec(struct b43_wldev *dev,
|
||||
struct b43_chanspec chanspec)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
const struct b43_nphy_channeltab_entry *tabent;
|
||||
|
||||
u8 tmp;
|
||||
u8 channel = chanspec.channel;
|
||||
|
||||
if (dev->phy.rev >= 3) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
nphy->radio_chanspec = chanspec;
|
||||
|
||||
if (chanspec.b_width != nphy->b_width)
|
||||
; /* TODO: BMAC BW Set (chanspec.b_width) */
|
||||
|
||||
/* TODO: use defines */
|
||||
if (chanspec.b_width == 3) {
|
||||
if (chanspec.sideband == 2)
|
||||
b43_phy_set(dev, B43_NPHY_RXCTL,
|
||||
B43_NPHY_RXCTL_BSELU20);
|
||||
else
|
||||
b43_phy_mask(dev, B43_NPHY_RXCTL,
|
||||
~B43_NPHY_RXCTL_BSELU20);
|
||||
}
|
||||
|
||||
if (dev->phy.rev >= 3) {
|
||||
tmp = (chanspec.b_freq == 1) ? 4 : 0;
|
||||
b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
|
||||
/* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */
|
||||
/* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */
|
||||
} else {
|
||||
tabent = b43_nphy_get_chantabent(dev, channel);
|
||||
if (!tabent)
|
||||
return -ESRCH;
|
||||
|
||||
tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050;
|
||||
b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
|
||||
b43_radio_2055_setup(dev, tabent);
|
||||
b43_nphy_chanspec_setup(dev, tabent, chanspec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tune the hardware to a new channel */
|
||||
static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
struct b43_chanspec chanspec;
|
||||
chanspec = nphy->radio_chanspec;
|
||||
chanspec.channel = channel;
|
||||
|
||||
return b43_nphy_set_chanspec(dev, chanspec);
|
||||
}
|
||||
|
||||
static int b43_nphy_op_allocate(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy;
|
||||
|
@ -3242,9 +3469,41 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
|
|||
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
|
||||
static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
bool blocked)
|
||||
{//TODO
|
||||
{
|
||||
if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
|
||||
b43err(dev->wl, "MAC not suspended\n");
|
||||
|
||||
if (blocked) {
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
|
||||
~B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
if (dev->phy.rev >= 3) {
|
||||
b43_radio_mask(dev, 0x09, ~0x2);
|
||||
|
||||
b43_radio_write(dev, 0x204D, 0);
|
||||
b43_radio_write(dev, 0x2053, 0);
|
||||
b43_radio_write(dev, 0x2058, 0);
|
||||
b43_radio_write(dev, 0x205E, 0);
|
||||
b43_radio_mask(dev, 0x2062, ~0xF0);
|
||||
b43_radio_write(dev, 0x2064, 0);
|
||||
|
||||
b43_radio_write(dev, 0x304D, 0);
|
||||
b43_radio_write(dev, 0x3053, 0);
|
||||
b43_radio_write(dev, 0x3058, 0);
|
||||
b43_radio_write(dev, 0x305E, 0);
|
||||
b43_radio_mask(dev, 0x3062, ~0xF0);
|
||||
b43_radio_write(dev, 0x3064, 0);
|
||||
}
|
||||
} else {
|
||||
if (dev->phy.rev >= 3) {
|
||||
/* TODO: b43_radio_init2056(dev); */
|
||||
/* TODO: PHY Set Channel Spec (dev, radio_chanspec) */
|
||||
} else {
|
||||
b43_radio_init2055(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||
|
|
|
@ -711,6 +711,8 @@
|
|||
#define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */
|
||||
#define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */
|
||||
|
||||
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
|
||||
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
|
||||
|
||||
|
||||
/* Broadcom 2055 radio registers */
|
||||
|
@ -924,6 +926,13 @@
|
|||
|
||||
struct b43_wldev;
|
||||
|
||||
struct b43_chanspec {
|
||||
u8 channel;
|
||||
u8 sideband;
|
||||
u8 b_width;
|
||||
u8 b_freq;
|
||||
};
|
||||
|
||||
struct b43_phy_n_iq_comp {
|
||||
s16 a0;
|
||||
s16 b0;
|
||||
|
@ -975,7 +984,8 @@ struct b43_phy_n {
|
|||
u16 papd_epsilon_offset[2];
|
||||
s32 preamble_override;
|
||||
u32 bb_mult_save;
|
||||
u16 radio_chanspec;
|
||||
u8 b_width;
|
||||
struct b43_chanspec radio_chanspec;
|
||||
|
||||
bool gain_boost;
|
||||
bool elna_gain_config;
|
||||
|
@ -991,6 +1001,7 @@ struct b43_phy_n {
|
|||
u16 txiqlocal_bestc[11];
|
||||
bool txiqlocal_coeffsvalid;
|
||||
struct b43_phy_n_txpwrindex txpwrindex[2];
|
||||
struct b43_chanspec txiqlocal_chanspec;
|
||||
|
||||
u8 txrx_chain;
|
||||
u16 tx_rx_cal_phy_saveregs[11];
|
||||
|
@ -1006,12 +1017,12 @@ struct b43_phy_n {
|
|||
bool gband_spurwar_en;
|
||||
|
||||
bool ipa2g_on;
|
||||
u8 iqcal_chanspec_2G;
|
||||
u8 rssical_chanspec_2G;
|
||||
struct b43_chanspec iqcal_chanspec_2G;
|
||||
struct b43_chanspec rssical_chanspec_2G;
|
||||
|
||||
bool ipa5g_on;
|
||||
u8 iqcal_chanspec_5G;
|
||||
u8 rssical_chanspec_5G;
|
||||
struct b43_chanspec iqcal_chanspec_5G;
|
||||
struct b43_chanspec rssical_chanspec_5G;
|
||||
|
||||
struct b43_phy_n_rssical_cache rssical_cache;
|
||||
struct b43_phy_n_cal_cache cal_cache;
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
|
||||
struct b43_phy_n_sfo_cfg {
|
||||
u16 phy_bw1a;
|
||||
u16 phy_bw2;
|
||||
u16 phy_bw3;
|
||||
u16 phy_bw4;
|
||||
u16 phy_bw5;
|
||||
u16 phy_bw6;
|
||||
};
|
||||
|
||||
struct b43_nphy_channeltab_entry {
|
||||
/* The channel number */
|
||||
u8 channel;
|
||||
|
|
|
@ -6102,7 +6102,7 @@ static const struct net_device_ops ipw2100_netdev_ops = {
|
|||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
/* Look into using netdev destructor to shutdown ieee80211? */
|
||||
/* Look into using netdev destructor to shutdown libipw? */
|
||||
|
||||
static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
|
||||
void __iomem * base_addr,
|
||||
|
@ -6112,7 +6112,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
|
|||
struct ipw2100_priv *priv;
|
||||
struct net_device *dev;
|
||||
|
||||
dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0);
|
||||
dev = alloc_libipw(sizeof(struct ipw2100_priv), 0);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
priv = libipw_priv(dev);
|
||||
|
@ -6425,7 +6425,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
sysfs_remove_group(&pci_dev->dev.kobj,
|
||||
&ipw2100_attribute_group);
|
||||
|
||||
free_ieee80211(dev, 0);
|
||||
free_libipw(dev, 0);
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
}
|
||||
|
||||
|
@ -6483,10 +6483,10 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
|
|||
if (dev->base_addr)
|
||||
iounmap((void __iomem *)dev->base_addr);
|
||||
|
||||
/* wiphy_unregister needs to be here, before free_ieee80211 */
|
||||
/* wiphy_unregister needs to be here, before free_libipw */
|
||||
wiphy_unregister(priv->ieee->wdev.wiphy);
|
||||
kfree(priv->ieee->bg_band.channels);
|
||||
free_ieee80211(dev, 0);
|
||||
free_libipw(dev, 0);
|
||||
}
|
||||
|
||||
pci_release_regions(pci_dev);
|
||||
|
|
|
@ -11666,7 +11666,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
|
|||
if (priv->prom_net_dev)
|
||||
return -EPERM;
|
||||
|
||||
priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1);
|
||||
priv->prom_net_dev = alloc_libipw(sizeof(struct ipw_prom_priv), 1);
|
||||
if (priv->prom_net_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -11685,7 +11685,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
|
|||
|
||||
rc = register_netdev(priv->prom_net_dev);
|
||||
if (rc) {
|
||||
free_ieee80211(priv->prom_net_dev, 1);
|
||||
free_libipw(priv->prom_net_dev, 1);
|
||||
priv->prom_net_dev = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
@ -11699,7 +11699,7 @@ static void ipw_prom_free(struct ipw_priv *priv)
|
|||
return;
|
||||
|
||||
unregister_netdev(priv->prom_net_dev);
|
||||
free_ieee80211(priv->prom_net_dev, 1);
|
||||
free_libipw(priv->prom_net_dev, 1);
|
||||
|
||||
priv->prom_net_dev = NULL;
|
||||
}
|
||||
|
@ -11727,7 +11727,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
|
|||
struct ipw_priv *priv;
|
||||
int i;
|
||||
|
||||
net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0);
|
||||
net_dev = alloc_libipw(sizeof(struct ipw_priv), 0);
|
||||
if (net_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -11747,7 +11747,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
|
|||
mutex_init(&priv->mutex);
|
||||
if (pci_enable_device(pdev)) {
|
||||
err = -ENODEV;
|
||||
goto out_free_ieee80211;
|
||||
goto out_free_libipw;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
@ -11874,8 +11874,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
|
|||
out_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
out_free_ieee80211:
|
||||
free_ieee80211(priv->net_dev, 0);
|
||||
out_free_libipw:
|
||||
free_libipw(priv->net_dev, 0);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -11942,11 +11942,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
|
|||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
/* wiphy_unregister needs to be here, before free_ieee80211 */
|
||||
/* wiphy_unregister needs to be here, before free_libipw */
|
||||
wiphy_unregister(priv->ieee->wdev.wiphy);
|
||||
kfree(priv->ieee->a_band.channels);
|
||||
kfree(priv->ieee->bg_band.channels);
|
||||
free_ieee80211(priv->net_dev, 0);
|
||||
free_libipw(priv->net_dev, 0);
|
||||
free_firmware();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
extern u32 libipw_debug_level;
|
||||
#define LIBIPW_DEBUG(level, fmt, args...) \
|
||||
do { if (libipw_debug_level & (level)) \
|
||||
printk(KERN_DEBUG "ieee80211: %c %s " fmt, \
|
||||
printk(KERN_DEBUG "libipw: %c %s " fmt, \
|
||||
in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
|
||||
static inline bool libipw_ratelimit_debug(u32 level)
|
||||
{
|
||||
|
@ -116,8 +116,8 @@ static inline bool libipw_ratelimit_debug(u32 level)
|
|||
#define LIBIPW_DL_RX (1<<9)
|
||||
#define LIBIPW_DL_QOS (1<<31)
|
||||
|
||||
#define LIBIPW_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
|
||||
#define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
|
||||
#define LIBIPW_ERROR(f, a...) printk(KERN_ERR "libipw: " f, ## a)
|
||||
#define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "libipw: " f, ## a)
|
||||
#define LIBIPW_DEBUG_INFO(f, a...) LIBIPW_DEBUG(LIBIPW_DL_INFO, f, ## a)
|
||||
|
||||
#define LIBIPW_DEBUG_WX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_WX, f, ## a)
|
||||
|
@ -905,7 +905,7 @@ struct libipw_device {
|
|||
struct libipw_reassoc_request * req);
|
||||
|
||||
/* This must be the last item so that it points to the data
|
||||
* allocated beyond this structure by alloc_ieee80211 */
|
||||
* allocated beyond this structure by alloc_libipw */
|
||||
u8 priv[0];
|
||||
};
|
||||
|
||||
|
@ -1017,9 +1017,9 @@ static inline int libipw_is_cck_rate(u8 rate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ieee80211.c */
|
||||
extern void free_ieee80211(struct net_device *dev, int monitor);
|
||||
extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
|
||||
/* libipw.c */
|
||||
extern void free_libipw(struct net_device *dev, int monitor);
|
||||
extern struct net_device *alloc_libipw(int sizeof_priv, int monitor);
|
||||
extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
|
||||
|
||||
extern void libipw_networks_age(struct libipw_device *ieee,
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
#include "libipw.h"
|
||||
|
||||
#define DRV_DESCRIPTION "802.11 data/management/control stack"
|
||||
#define DRV_NAME "ieee80211"
|
||||
#define DRV_NAME "libipw"
|
||||
#define DRV_VERSION LIBIPW_VERSION
|
||||
#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
|
||||
|
||||
|
@ -140,7 +140,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu)
|
|||
}
|
||||
EXPORT_SYMBOL(libipw_change_mtu);
|
||||
|
||||
struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
|
||||
struct net_device *alloc_libipw(int sizeof_priv, int monitor)
|
||||
{
|
||||
struct libipw_device *ieee;
|
||||
struct net_device *dev;
|
||||
|
@ -222,8 +222,9 @@ failed_free_netdev:
|
|||
failed:
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_libipw);
|
||||
|
||||
void free_ieee80211(struct net_device *dev, int monitor)
|
||||
void free_libipw(struct net_device *dev, int monitor)
|
||||
{
|
||||
struct libipw_device *ieee = netdev_priv(dev);
|
||||
|
||||
|
@ -237,6 +238,7 @@ void free_ieee80211(struct net_device *dev, int monitor)
|
|||
|
||||
free_netdev(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(free_libipw);
|
||||
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
|
||||
|
@ -291,7 +293,7 @@ static int __init libipw_init(void)
|
|||
struct proc_dir_entry *e;
|
||||
|
||||
libipw_debug_level = debug;
|
||||
libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
|
||||
libipw_proc = proc_mkdir("ieee80211", init_net.proc_net);
|
||||
if (libipw_proc == NULL) {
|
||||
LIBIPW_ERROR("Unable to create " DRV_NAME
|
||||
" proc directory\n");
|
||||
|
@ -331,6 +333,3 @@ MODULE_PARM_DESC(debug, "debug output mask");
|
|||
|
||||
module_exit(libipw_exit);
|
||||
module_init(libipw_init);
|
||||
|
||||
EXPORT_SYMBOL(alloc_ieee80211);
|
||||
EXPORT_SYMBOL(free_ieee80211);
|
||||
|
|
|
@ -9,7 +9,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
|
|||
|
||||
# AGN
|
||||
obj-$(CONFIG_IWLAGN) += iwlagn.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
|
||||
|
||||
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-agn-led.h"
|
||||
|
|
|
@ -78,6 +78,8 @@
|
|||
/* RSSI to dBm */
|
||||
#define IWL39_RSSI_OFFSET 95
|
||||
|
||||
#define IWL_DEFAULT_TX_POWER 0x0F
|
||||
|
||||
/*
|
||||
* EEPROM related constants, enums, and structures.
|
||||
*/
|
||||
|
|
|
@ -372,11 +372,11 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
|||
}
|
||||
}
|
||||
|
||||
priv->sta_supp_rates = sta->supp_rates[sband->band];
|
||||
priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
|
||||
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
|
||||
if (sband->band == IEEE80211_BAND_5GHZ) {
|
||||
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
|
||||
priv->sta_supp_rates = priv->sta_supp_rates <<
|
||||
priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
|
||||
IWL_FIRST_OFDM_RATE;
|
||||
}
|
||||
|
||||
|
@ -946,7 +946,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
|
|||
|
||||
spin_unlock_irqrestore(&rs_sta->lock, flags);
|
||||
|
||||
rssi = priv->last_rx_rssi;
|
||||
rssi = priv->_3945.last_rx_rssi;
|
||||
if (rssi == 0)
|
||||
rssi = IWL_MIN_RSSI_VAL;
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
|
|||
next_rate = IWL_RATE_6M_INDEX;
|
||||
break;
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
|
||||
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
|
||||
iwl_is_associated(priv)) {
|
||||
if (rate == IWL_RATE_11M_INDEX)
|
||||
next_rate = IWL_RATE_5M_INDEX;
|
||||
|
@ -359,7 +359,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
|||
(int)sizeof(struct iwl3945_notif_statistics),
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
||||
memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
|
||||
memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -705,9 +705,10 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
|
|||
iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
|
||||
|
||||
if (network_packet) {
|
||||
priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
|
||||
priv->last_tsf = le64_to_cpu(rx_end->timestamp);
|
||||
priv->last_rx_rssi = rx_status.signal;
|
||||
priv->_3945.last_beacon_time =
|
||||
le32_to_cpu(rx_end->beacon_timestamp);
|
||||
priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
|
||||
priv->_3945.last_rx_rssi = rx_status.signal;
|
||||
priv->last_rx_noise = rx_status.noise;
|
||||
}
|
||||
|
||||
|
@ -956,7 +957,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
|
|||
iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
|
||||
|
||||
iwl_write_direct32(priv, FH39_TSSR_CBB_BASE,
|
||||
priv->shared_phys);
|
||||
priv->_3945.shared_phys);
|
||||
|
||||
iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
|
||||
FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
|
||||
|
@ -1606,7 +1607,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
|
|||
int power;
|
||||
|
||||
/* Get this chnlgrp's rate-to-max/clip-powers table */
|
||||
clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
|
||||
clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
|
||||
|
||||
/* Get this channel's rate-to-current-power settings table */
|
||||
power_info = ch_info->power_info;
|
||||
|
@ -1732,7 +1733,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
/* Get this chnlgrp's rate-to-max/clip-powers table */
|
||||
clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
|
||||
clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
|
||||
|
||||
/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
|
||||
for (scan_tbl_index = 0;
|
||||
|
@ -1997,13 +1998,13 @@ void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
|
|||
|
||||
reschedule:
|
||||
queue_delayed_work(priv->workqueue,
|
||||
&priv->thermal_periodic, REG_RECALIB_PERIOD * HZ);
|
||||
&priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
|
||||
}
|
||||
|
||||
static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
thermal_periodic.work);
|
||||
_3945.thermal_periodic.work);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
@ -2139,7 +2140,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
|
|||
* power peaks, without too much distortion (clipping).
|
||||
*/
|
||||
/* we'll fill in this array with h/w max power levels */
|
||||
clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers;
|
||||
clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
|
||||
|
||||
/* divide factory saturation power by 2 to find -3dB level */
|
||||
satur_pwr = (s8) (group->saturation_power >> 1);
|
||||
|
@ -2223,7 +2224,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
|
|||
iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
|
||||
|
||||
/* Get this chnlgrp's rate->max/clip-powers table */
|
||||
clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
|
||||
clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
|
||||
|
||||
/* calculate power index *adjustment* value according to
|
||||
* diff between current temperature and factory temperature */
|
||||
|
@ -2331,7 +2332,7 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
|||
{
|
||||
int txq_id = txq->q.id;
|
||||
|
||||
struct iwl3945_shared *shared_data = priv->shared_virt;
|
||||
struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
|
||||
|
||||
shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
|
||||
|
||||
|
@ -2431,7 +2432,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
|
|||
/* If an OFDM rate is used, have it fall back to the
|
||||
* 1M CCK rates */
|
||||
|
||||
if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
|
||||
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
|
||||
iwl_is_associated(priv)) {
|
||||
|
||||
index = IWL_FIRST_CCK_RATE;
|
||||
|
@ -2470,10 +2471,11 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
|
|||
memset((void *)&priv->hw_params, 0,
|
||||
sizeof(struct iwl_hw_params));
|
||||
|
||||
priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
&priv->shared_phys, GFP_KERNEL);
|
||||
if (!priv->shared_virt) {
|
||||
priv->_3945.shared_virt =
|
||||
dma_alloc_coherent(&priv->pci_dev->dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
&priv->_3945.shared_phys, GFP_KERNEL);
|
||||
if (!priv->_3945.shared_virt) {
|
||||
IWL_ERR(priv, "failed to allocate pci memory\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return -ENOMEM;
|
||||
|
@ -2536,13 +2538,13 @@ void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
|
|||
|
||||
void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
INIT_DELAYED_WORK(&priv->thermal_periodic,
|
||||
INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
|
||||
iwl3945_bg_reg_txpower_periodic);
|
||||
}
|
||||
|
||||
void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
cancel_delayed_work(&priv->thermal_periodic);
|
||||
cancel_delayed_work(&priv->_3945.thermal_periodic);
|
||||
}
|
||||
|
||||
/* check contents of special bootstrap uCode SRAM */
|
||||
|
|
|
@ -502,14 +502,14 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
|
|||
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
|
||||
}
|
||||
|
||||
static const u16 default_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_AC3,
|
||||
IWL_TX_FIFO_AC2,
|
||||
IWL_TX_FIFO_AC1,
|
||||
IWL_TX_FIFO_AC0,
|
||||
static const s8 default_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
IWL_TX_FIFO_VI,
|
||||
IWL_TX_FIFO_BE,
|
||||
IWL_TX_FIFO_BK,
|
||||
IWL49_CMD_FIFO_NUM,
|
||||
IWL_TX_FIFO_HCCA_1,
|
||||
IWL_TX_FIFO_HCCA_2
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
};
|
||||
|
||||
static int iwl4965_alive_notify(struct iwl_priv *priv)
|
||||
|
@ -589,9 +589,15 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
|||
/* reset to 0 to enable all the queue first */
|
||||
priv->txq_ctx_active_msk = 0;
|
||||
/* Map each Tx/cmd queue to its corresponding fifo */
|
||||
BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
|
||||
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
|
||||
int ac = default_queue_to_tx_fifo[i];
|
||||
|
||||
iwl_txq_ctx_activate(priv, i);
|
||||
|
||||
if (ac == IWL_TX_FIFO_UNUSED)
|
||||
continue;
|
||||
|
||||
iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "iwl-io.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-agn-led.h"
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-6000-hw.h"
|
||||
|
@ -63,14 +64,17 @@
|
|||
#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
|
||||
#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
|
||||
|
||||
static const u16 iwl5000_default_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_AC3,
|
||||
IWL_TX_FIFO_AC2,
|
||||
IWL_TX_FIFO_AC1,
|
||||
IWL_TX_FIFO_AC0,
|
||||
static const s8 iwl5000_default_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
IWL_TX_FIFO_VI,
|
||||
IWL_TX_FIFO_BE,
|
||||
IWL_TX_FIFO_BK,
|
||||
IWL50_CMD_FIFO_NUM,
|
||||
IWL_TX_FIFO_HCCA_1,
|
||||
IWL_TX_FIFO_HCCA_2
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
IWL_TX_FIFO_UNUSED,
|
||||
};
|
||||
|
||||
/* NIC configuration for 5000 series */
|
||||
|
@ -579,9 +583,9 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
|
|||
|
||||
txq->sched_retry = scd_retry;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
|
||||
IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
|
||||
active ? "Activate" : "Deactivate",
|
||||
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
|
||||
scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
|
||||
}
|
||||
|
||||
int iwl5000_alive_notify(struct iwl_priv *priv)
|
||||
|
@ -656,25 +660,21 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
|
|||
/* reset to 0 to enable all the queue first */
|
||||
priv->txq_ctx_active_msk = 0;
|
||||
/* map qos queues to fifos one-to-one */
|
||||
BUILD_BUG_ON(ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo) != 10);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
|
||||
int ac = iwl5000_default_queue_to_tx_fifo[i];
|
||||
|
||||
iwl_txq_ctx_activate(priv, i);
|
||||
|
||||
if (ac == IWL_TX_FIFO_UNUSED)
|
||||
continue;
|
||||
|
||||
iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO - need to initialize these queues and map them to FIFOs
|
||||
* in the loop above, not only mark them as active. We do this
|
||||
* because we want the first aggregation queue to be queue #10,
|
||||
* but do not use 8 or 9 otherwise yet.
|
||||
*/
|
||||
iwl_txq_ctx_activate(priv, 7);
|
||||
iwl_txq_ctx_activate(priv, 8);
|
||||
iwl_txq_ctx_activate(priv, 9);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
|
||||
iwl_send_wimax_coex(priv);
|
||||
|
||||
iwl5000_set_Xtal_calib(priv);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-6000-hw.h"
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/sched.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-helpers.h"
|
||||
|
||||
#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
|
||||
|
||||
/* Free dram table */
|
||||
void iwl_free_isr_ict(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->_agn.ict_tbl_vir) {
|
||||
dma_free_coherent(&priv->pci_dev->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
priv->_agn.ict_tbl_vir,
|
||||
priv->_agn.ict_tbl_dma);
|
||||
priv->_agn.ict_tbl_vir = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* allocate dram shared table it is a PAGE_SIZE aligned
|
||||
* also reset all data related to ICT table interrupt.
|
||||
*/
|
||||
int iwl_alloc_isr_ict(struct iwl_priv *priv)
|
||||
{
|
||||
|
||||
if (priv->cfg->use_isr_legacy)
|
||||
return 0;
|
||||
/* allocate shrared data table */
|
||||
priv->_agn.ict_tbl_vir =
|
||||
dma_alloc_coherent(&priv->pci_dev->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
&priv->_agn.ict_tbl_dma, GFP_KERNEL);
|
||||
if (!priv->_agn.ict_tbl_vir)
|
||||
return -ENOMEM;
|
||||
|
||||
/* align table to PAGE_SIZE boundry */
|
||||
priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE);
|
||||
|
||||
IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
|
||||
(unsigned long long)priv->_agn.ict_tbl_dma,
|
||||
(unsigned long long)priv->_agn.aligned_ict_tbl_dma,
|
||||
(int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
|
||||
|
||||
priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir +
|
||||
(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma);
|
||||
|
||||
IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
|
||||
priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir,
|
||||
(int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
|
||||
|
||||
/* reset table and index to all 0 */
|
||||
memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
|
||||
priv->_agn.ict_index = 0;
|
||||
|
||||
/* add periodic RX interrupt */
|
||||
priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Device is going up inform it about using ICT interrupt table,
|
||||
* also we need to tell the driver to start using ICT interrupt.
|
||||
*/
|
||||
int iwl_reset_ict(struct iwl_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
if (!priv->_agn.ict_tbl_vir)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_disable_interrupts(priv);
|
||||
|
||||
memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
|
||||
|
||||
val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT;
|
||||
|
||||
val |= CSR_DRAM_INT_TBL_ENABLE;
|
||||
val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
|
||||
|
||||
IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
|
||||
"aligned dma address %Lx\n",
|
||||
val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma);
|
||||
|
||||
iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
|
||||
priv->_agn.use_ict = true;
|
||||
priv->_agn.ict_index = 0;
|
||||
iwl_write32(priv, CSR_INT, priv->inta_mask);
|
||||
iwl_enable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Device is going down disable ict interrupt usage */
|
||||
void iwl_disable_ict(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->_agn.use_ict = false;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t iwl_isr(int irq, void *data)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
u32 inta, inta_mask;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
u32 inta_fh;
|
||||
#endif
|
||||
if (!priv)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
* If we have something to service, the tasklet will re-enable ints.
|
||||
* If we *don't* have something, we'll re-enable before leaving here. */
|
||||
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
|
||||
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
|
||||
|
||||
/* Discover which interrupts are active/pending */
|
||||
inta = iwl_read32(priv, CSR_INT);
|
||||
|
||||
/* Ignore interrupt if there's nothing in NIC to service.
|
||||
* This may be due to IRQ shared with another device,
|
||||
* or due to sporadic interrupts thrown from our NIC. */
|
||||
if (!inta) {
|
||||
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
|
||||
goto none;
|
||||
}
|
||||
|
||||
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
|
||||
/* Hardware disappeared. It might have already raised
|
||||
* an interrupt */
|
||||
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
|
||||
goto unplugged;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
|
||||
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
|
||||
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
|
||||
"fh 0x%08x\n", inta, inta_mask, inta_fh);
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->_agn.inta |= inta;
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&priv->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
unplugged:
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
/* re-enable interrupts here since we don't have anything to service. */
|
||||
/* only Re-enable if diabled by irq and no schedules tasklet. */
|
||||
if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* interrupt handler using ict table, with this interrupt driver will
|
||||
* stop using INTA register to get device's interrupt, reading this register
|
||||
* is expensive, device will write interrupts in ICT dram table, increment
|
||||
* index then will fire interrupt to driver, driver will OR all ICT table
|
||||
* entries from current index up to table entry with 0 value. the result is
|
||||
* the interrupt we need to service, driver will set the entries back to 0 and
|
||||
* set index.
|
||||
*/
|
||||
irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
u32 inta, inta_mask;
|
||||
u32 val = 0;
|
||||
|
||||
if (!priv)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* dram interrupt table not set yet,
|
||||
* use legacy interrupt.
|
||||
*/
|
||||
if (!priv->_agn.use_ict)
|
||||
return iwl_isr(irq, data);
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
* If we have something to service, the tasklet will re-enable ints.
|
||||
* If we *don't* have something, we'll re-enable before leaving here.
|
||||
*/
|
||||
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
|
||||
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
|
||||
|
||||
|
||||
/* Ignore interrupt if there's nothing in NIC to service.
|
||||
* This may be due to IRQ shared with another device,
|
||||
* or due to sporadic interrupts thrown from our NIC. */
|
||||
if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) {
|
||||
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
|
||||
goto none;
|
||||
}
|
||||
|
||||
/* read all entries that not 0 start with ict_index */
|
||||
while (priv->_agn.ict_tbl[priv->_agn.ict_index]) {
|
||||
|
||||
val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]);
|
||||
IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
|
||||
priv->_agn.ict_index,
|
||||
le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]));
|
||||
priv->_agn.ict_tbl[priv->_agn.ict_index] = 0;
|
||||
priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index,
|
||||
ICT_COUNT);
|
||||
|
||||
}
|
||||
|
||||
/* We should not get this value, just ignore it. */
|
||||
if (val == 0xffffffff)
|
||||
val = 0;
|
||||
|
||||
/*
|
||||
* this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
|
||||
* (bit 15 before shifting it to 31) to clear when using interrupt
|
||||
* coalescing. fortunately, bits 18 and 19 stay set when this happens
|
||||
* so we use them to decide on the real state of the Rx bit.
|
||||
* In order words, bit 15 is set if bit 18 or bit 19 are set.
|
||||
*/
|
||||
if (val & 0xC0000)
|
||||
val |= 0x8000;
|
||||
|
||||
inta = (0xff & val) | ((0xff00 & val) << 16);
|
||||
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
|
||||
inta, inta_mask, val);
|
||||
|
||||
inta &= priv->inta_mask;
|
||||
priv->_agn.inta |= inta;
|
||||
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&priv->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) {
|
||||
/* Allow interrupt if was disabled by this handler and
|
||||
* no tasklet was schedules, We should not enable interrupt,
|
||||
* tasklet will enable it.
|
||||
*/
|
||||
iwl_enable_interrupts(priv);
|
||||
}
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
/* re-enable interrupts here since we don't have anything to service.
|
||||
* only Re-enable if disabled by irq.
|
||||
*/
|
||||
if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_NONE;
|
||||
}
|
|
@ -597,10 +597,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
|
|||
struct ieee80211_hdr *hdr,
|
||||
enum iwl_table_type rate_type)
|
||||
{
|
||||
if (hdr && is_multicast_ether_addr(hdr->addr1) &&
|
||||
lq_sta->active_rate_basic)
|
||||
return lq_sta->active_rate_basic;
|
||||
|
||||
if (is_legacy(rate_type)) {
|
||||
return lq_sta->active_legacy_rate;
|
||||
} else {
|
||||
|
@ -2552,7 +2548,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
|
|||
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
|
||||
lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
|
||||
lq_sta->active_rate_basic = priv->active_rate_basic;
|
||||
lq_sta->band = priv->band;
|
||||
/*
|
||||
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
|
||||
|
@ -2956,12 +2951,8 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
|
|||
desc += sprintf(buff+desc,
|
||||
"Bit Rate= %d Mb/s\n",
|
||||
iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
|
||||
desc += sprintf(buff+desc,
|
||||
"Signal Level= %d dBm\tNoise Level= %d dBm\n",
|
||||
priv->last_rx_rssi, priv->last_rx_noise);
|
||||
desc += sprintf(buff+desc,
|
||||
"Tsf= 0x%llx\tBeacon time= 0x%08X\n",
|
||||
priv->last_tsf, priv->last_beacon_time);
|
||||
desc += sprintf(buff+desc, "Noise Level= %d dBm\n",
|
||||
priv->last_rx_noise);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
|
||||
return ret;
|
||||
|
|
|
@ -411,7 +411,6 @@ struct iwl_lq_sta {
|
|||
u16 active_siso_rate;
|
||||
u16 active_mimo2_rate;
|
||||
u16 active_mimo3_rate;
|
||||
u16 active_rate_basic;
|
||||
s8 max_rate_idx; /* Max rate set by user */
|
||||
u8 missed_rate_counter;
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "iwl-helpers.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-calib.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -1258,9 +1259,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
|||
/* Ack/clear/reset pending uCode interrupts.
|
||||
* Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
|
||||
*/
|
||||
iwl_write32(priv, CSR_INT, priv->inta);
|
||||
iwl_write32(priv, CSR_INT, priv->_agn.inta);
|
||||
|
||||
inta = priv->inta;
|
||||
inta = priv->_agn.inta;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
|
||||
|
@ -1273,8 +1274,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
|||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* saved interrupt in inta variable now we can reset priv->inta */
|
||||
priv->inta = 0;
|
||||
/* saved interrupt in inta variable now we can reset priv->_agn.inta */
|
||||
priv->_agn.inta = 0;
|
||||
|
||||
/* Now service all interrupt bits discovered above. */
|
||||
if (inta & CSR_INT_BIT_HW_ERR) {
|
||||
|
@ -2102,8 +2103,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
|
||||
priv->active_rate = priv->rates_mask;
|
||||
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
|
||||
priv->active_rate = IWL_RATES_MASK;
|
||||
|
||||
/* Configure Tx antenna selection based on H/W config */
|
||||
if (priv->cfg->ops->hcmd->set_tx_ant)
|
||||
|
@ -2144,18 +2144,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
|
||||
iwl_power_update_mode(priv, true);
|
||||
|
||||
/* reassociate for ADHOC mode */
|
||||
if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
|
||||
priv->vif);
|
||||
if (beacon)
|
||||
iwl_mac_beacon_update(priv->hw, beacon);
|
||||
}
|
||||
|
||||
|
||||
if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
|
||||
iwl_set_mode(priv, priv->iw_mode);
|
||||
|
||||
return;
|
||||
|
||||
restart:
|
||||
|
@ -2881,7 +2869,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
/* If we are getting WEP group key and we didn't receive any key mapping
|
||||
* so far, we are in legacy wep mode (group key only), otherwise we are
|
||||
|
@ -2917,6 +2904,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
|
@ -3121,87 +3109,6 @@ static ssize_t store_tx_power(struct device *d,
|
|||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
||||
static ssize_t show_flags(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
|
||||
}
|
||||
|
||||
static ssize_t store_flags(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
u32 flags;
|
||||
int ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
flags = (u32)val;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
|
||||
/* Cancel any currently running scans... */
|
||||
if (iwl_scan_cancel_timeout(priv, 100))
|
||||
IWL_WARN(priv, "Could not cancel scan.\n");
|
||||
else {
|
||||
IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags);
|
||||
priv->staging_rxon.flags = cpu_to_le32(flags);
|
||||
iwlcore_commit_rxon(priv);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
|
||||
|
||||
static ssize_t show_filter_flags(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "0x%04X\n",
|
||||
le32_to_cpu(priv->active_rxon.filter_flags));
|
||||
}
|
||||
|
||||
static ssize_t store_filter_flags(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
u32 filter_flags;
|
||||
int ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
filter_flags = (u32)val;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
|
||||
/* Cancel any currently running scans... */
|
||||
if (iwl_scan_cancel_timeout(priv, 100))
|
||||
IWL_WARN(priv, "Could not cancel scan.\n");
|
||||
else {
|
||||
IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
|
||||
"0x%04X\n", filter_flags);
|
||||
priv->staging_rxon.filter_flags =
|
||||
cpu_to_le32(filter_flags);
|
||||
iwlcore_commit_rxon(priv);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
|
||||
store_filter_flags);
|
||||
|
||||
|
||||
static ssize_t show_statistics(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -3391,7 +3298,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
|||
priv->qos_data.qos_active = 0;
|
||||
priv->qos_data.qos_cap.val = 0;
|
||||
|
||||
priv->rates_mask = IWL_RATES_MASK;
|
||||
/* Set the tx_power_user_lmt to the lowest power level
|
||||
* this value will get overwritten by channel max power avg
|
||||
* from eeprom */
|
||||
|
@ -3427,8 +3333,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_flags.attr,
|
||||
&dev_attr_filter_flags.attr,
|
||||
&dev_attr_statistics.attr,
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* 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 <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __iwl_agn_h__
|
||||
#define __iwl_agn_h__
|
||||
|
||||
#include "iwl-dev.h"
|
||||
|
||||
int iwl_reset_ict(struct iwl_priv *priv);
|
||||
void iwl_disable_ict(struct iwl_priv *priv);
|
||||
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);
|
||||
|
||||
#endif /* __iwl_agn_h__ */
|
|
@ -114,8 +114,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
|
|||
u32 iwl_debug_level;
|
||||
EXPORT_SYMBOL(iwl_debug_level);
|
||||
|
||||
static irqreturn_t iwl_isr(int irq, void *data);
|
||||
|
||||
/*
|
||||
* Parameter order:
|
||||
* rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
|
||||
|
@ -899,23 +897,10 @@ EXPORT_SYMBOL(iwl_full_rxon_required);
|
|||
|
||||
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
int rate_mask;
|
||||
|
||||
/* Set rate mask*/
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
|
||||
rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
|
||||
else
|
||||
rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
|
||||
|
||||
/* Find lowest valid rate */
|
||||
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
|
||||
i = iwl_rates[i].next_ieee) {
|
||||
if (rate_mask & (1 << i))
|
||||
return iwl_rates[i].plcp;
|
||||
}
|
||||
|
||||
/* No valid rate was found. Assign the lowest one */
|
||||
/*
|
||||
* Assign the lowest rate -- should really get this from
|
||||
* the beacon skb from mac80211.
|
||||
*/
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
|
||||
return IWL_RATE_1M_PLCP;
|
||||
else
|
||||
|
@ -1240,14 +1225,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
|
|||
if (!ch_info)
|
||||
ch_info = &priv->channel_info[0];
|
||||
|
||||
/*
|
||||
* in some case A channels are all non IBSS
|
||||
* in this case force B/G channel
|
||||
*/
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
|
||||
!(is_channel_ibss(ch_info)))
|
||||
ch_info = &priv->channel_info[0];
|
||||
|
||||
priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
|
||||
priv->band = ch_info->band;
|
||||
|
||||
|
@ -1282,7 +1259,6 @@ static void iwl_set_rate(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
priv->active_rate = 0;
|
||||
priv->active_rate_basic = 0;
|
||||
|
||||
for (i = 0; i < hw->n_bitrates; i++) {
|
||||
rate = &(hw->bitrates[i]);
|
||||
|
@ -1290,30 +1266,13 @@ static void iwl_set_rate(struct iwl_priv *priv)
|
|||
priv->active_rate |= (1 << rate->hw_value);
|
||||
}
|
||||
|
||||
IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n",
|
||||
priv->active_rate, priv->active_rate_basic);
|
||||
IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
|
||||
|
||||
/*
|
||||
* If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
|
||||
* otherwise set it to the default of all CCK rates and 6, 12, 24 for
|
||||
* OFDM
|
||||
*/
|
||||
if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
|
||||
priv->staging_rxon.cck_basic_rates =
|
||||
((priv->active_rate_basic &
|
||||
IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
|
||||
else
|
||||
priv->staging_rxon.cck_basic_rates =
|
||||
(IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
|
||||
priv->staging_rxon.cck_basic_rates =
|
||||
(IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
|
||||
|
||||
if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
|
||||
priv->staging_rxon.ofdm_basic_rates =
|
||||
((priv->active_rate_basic &
|
||||
(IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
|
||||
IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||
else
|
||||
priv->staging_rxon.ofdm_basic_rates =
|
||||
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||
priv->staging_rxon.ofdm_basic_rates =
|
||||
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||
}
|
||||
|
||||
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
|
@ -1397,7 +1356,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_irq_handle_error);
|
||||
|
||||
int iwl_apm_stop_master(struct iwl_priv *priv)
|
||||
static int iwl_apm_stop_master(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -1413,7 +1372,6 @@ int iwl_apm_stop_master(struct iwl_priv *priv)
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_apm_stop_master);
|
||||
|
||||
void iwl_apm_stop(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -1664,277 +1622,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_set_tx_power);
|
||||
|
||||
#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
|
||||
|
||||
/* Free dram table */
|
||||
void iwl_free_isr_ict(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->ict_tbl_vir) {
|
||||
dma_free_coherent(&priv->pci_dev->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
priv->ict_tbl_vir, priv->ict_tbl_dma);
|
||||
priv->ict_tbl_vir = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_free_isr_ict);
|
||||
|
||||
|
||||
/* allocate dram shared table it is a PAGE_SIZE aligned
|
||||
* also reset all data related to ICT table interrupt.
|
||||
*/
|
||||
int iwl_alloc_isr_ict(struct iwl_priv *priv)
|
||||
{
|
||||
|
||||
if (priv->cfg->use_isr_legacy)
|
||||
return 0;
|
||||
/* allocate shrared data table */
|
||||
priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
&priv->ict_tbl_dma, GFP_KERNEL);
|
||||
if (!priv->ict_tbl_vir)
|
||||
return -ENOMEM;
|
||||
|
||||
/* align table to PAGE_SIZE boundry */
|
||||
priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE);
|
||||
|
||||
IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
|
||||
(unsigned long long)priv->ict_tbl_dma,
|
||||
(unsigned long long)priv->aligned_ict_tbl_dma,
|
||||
(int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
|
||||
|
||||
priv->ict_tbl = priv->ict_tbl_vir +
|
||||
(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma);
|
||||
|
||||
IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
|
||||
priv->ict_tbl, priv->ict_tbl_vir,
|
||||
(int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
|
||||
|
||||
/* reset table and index to all 0 */
|
||||
memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
|
||||
priv->ict_index = 0;
|
||||
|
||||
/* add periodic RX interrupt */
|
||||
priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_alloc_isr_ict);
|
||||
|
||||
/* Device is going up inform it about using ICT interrupt table,
|
||||
* also we need to tell the driver to start using ICT interrupt.
|
||||
*/
|
||||
int iwl_reset_ict(struct iwl_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
if (!priv->ict_tbl_vir)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_disable_interrupts(priv);
|
||||
|
||||
memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
|
||||
|
||||
val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
|
||||
|
||||
val |= CSR_DRAM_INT_TBL_ENABLE;
|
||||
val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
|
||||
|
||||
IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
|
||||
"aligned dma address %Lx\n",
|
||||
val, (unsigned long long)priv->aligned_ict_tbl_dma);
|
||||
|
||||
iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
|
||||
priv->use_ict = true;
|
||||
priv->ict_index = 0;
|
||||
iwl_write32(priv, CSR_INT, priv->inta_mask);
|
||||
iwl_enable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_reset_ict);
|
||||
|
||||
/* Device is going down disable ict interrupt usage */
|
||||
void iwl_disable_ict(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->use_ict = false;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_disable_ict);
|
||||
|
||||
/* interrupt handler using ict table, with this interrupt driver will
|
||||
* stop using INTA register to get device's interrupt, reading this register
|
||||
* is expensive, device will write interrupts in ICT dram table, increment
|
||||
* index then will fire interrupt to driver, driver will OR all ICT table
|
||||
* entries from current index up to table entry with 0 value. the result is
|
||||
* the interrupt we need to service, driver will set the entries back to 0 and
|
||||
* set index.
|
||||
*/
|
||||
irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
u32 inta, inta_mask;
|
||||
u32 val = 0;
|
||||
|
||||
if (!priv)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* dram interrupt table not set yet,
|
||||
* use legacy interrupt.
|
||||
*/
|
||||
if (!priv->use_ict)
|
||||
return iwl_isr(irq, data);
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
* If we have something to service, the tasklet will re-enable ints.
|
||||
* If we *don't* have something, we'll re-enable before leaving here.
|
||||
*/
|
||||
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
|
||||
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
|
||||
|
||||
|
||||
/* Ignore interrupt if there's nothing in NIC to service.
|
||||
* This may be due to IRQ shared with another device,
|
||||
* or due to sporadic interrupts thrown from our NIC. */
|
||||
if (!priv->ict_tbl[priv->ict_index]) {
|
||||
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
|
||||
goto none;
|
||||
}
|
||||
|
||||
/* read all entries that not 0 start with ict_index */
|
||||
while (priv->ict_tbl[priv->ict_index]) {
|
||||
|
||||
val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]);
|
||||
IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
|
||||
priv->ict_index,
|
||||
le32_to_cpu(priv->ict_tbl[priv->ict_index]));
|
||||
priv->ict_tbl[priv->ict_index] = 0;
|
||||
priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
|
||||
ICT_COUNT);
|
||||
|
||||
}
|
||||
|
||||
/* We should not get this value, just ignore it. */
|
||||
if (val == 0xffffffff)
|
||||
val = 0;
|
||||
|
||||
/*
|
||||
* this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
|
||||
* (bit 15 before shifting it to 31) to clear when using interrupt
|
||||
* coalescing. fortunately, bits 18 and 19 stay set when this happens
|
||||
* so we use them to decide on the real state of the Rx bit.
|
||||
* In order words, bit 15 is set if bit 18 or bit 19 are set.
|
||||
*/
|
||||
if (val & 0xC0000)
|
||||
val |= 0x8000;
|
||||
|
||||
inta = (0xff & val) | ((0xff00 & val) << 16);
|
||||
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
|
||||
inta, inta_mask, val);
|
||||
|
||||
inta &= priv->inta_mask;
|
||||
priv->inta |= inta;
|
||||
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&priv->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) {
|
||||
/* Allow interrupt if was disabled by this handler and
|
||||
* no tasklet was schedules, We should not enable interrupt,
|
||||
* tasklet will enable it.
|
||||
*/
|
||||
iwl_enable_interrupts(priv);
|
||||
}
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
/* re-enable interrupts here since we don't have anything to service.
|
||||
* only Re-enable if disabled by irq.
|
||||
*/
|
||||
if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_isr_ict);
|
||||
|
||||
|
||||
static irqreturn_t iwl_isr(int irq, void *data)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
u32 inta, inta_mask;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
u32 inta_fh;
|
||||
#endif
|
||||
if (!priv)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
* If we have something to service, the tasklet will re-enable ints.
|
||||
* If we *don't* have something, we'll re-enable before leaving here. */
|
||||
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
|
||||
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
|
||||
|
||||
/* Discover which interrupts are active/pending */
|
||||
inta = iwl_read32(priv, CSR_INT);
|
||||
|
||||
/* Ignore interrupt if there's nothing in NIC to service.
|
||||
* This may be due to IRQ shared with another device,
|
||||
* or due to sporadic interrupts thrown from our NIC. */
|
||||
if (!inta) {
|
||||
IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
|
||||
goto none;
|
||||
}
|
||||
|
||||
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
|
||||
/* Hardware disappeared. It might have already raised
|
||||
* an interrupt */
|
||||
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
|
||||
goto unplugged;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
|
||||
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
|
||||
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
|
||||
"fh 0x%08x\n", inta, inta_mask, inta_fh);
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->inta |= inta;
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&priv->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
unplugged:
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
/* re-enable interrupts here since we don't have anything to service. */
|
||||
/* only Re-enable if diabled by irq and no schedules tasklet. */
|
||||
if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
irqreturn_t iwl_isr_legacy(int irq, void *data)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
|
@ -2564,11 +2251,6 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
if (priv->ibss_beacon)
|
||||
|
@ -2592,23 +2274,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_mac_beacon_update);
|
||||
|
||||
int iwl_set_mode(struct iwl_priv *priv, int mode)
|
||||
static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (mode == NL80211_IFTYPE_ADHOC) {
|
||||
const struct iwl_channel_info *ch_info;
|
||||
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
priv->band,
|
||||
le16_to_cpu(priv->staging_rxon.channel));
|
||||
|
||||
if (!ch_info || !is_channel_ibss(ch_info)) {
|
||||
IWL_ERR(priv, "channel %d not IBSS channel\n",
|
||||
le16_to_cpu(priv->staging_rxon.channel));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_connection_init_rx_config(priv, mode);
|
||||
iwl_connection_init_rx_config(priv, vif->type);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
@ -2617,18 +2285,10 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
|
|||
|
||||
iwl_clear_stations_table(priv);
|
||||
|
||||
/* dont commit rxon if rf-kill is on*/
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
||||
return 0;
|
||||
return iwlcore_commit_rxon(priv);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_mode);
|
||||
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
int err = 0;
|
||||
|
@ -2637,6 +2297,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (WARN_ON(!iwl_is_ready_rf(priv))) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->vif) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
|
||||
err = -EOPNOTSUPP;
|
||||
|
@ -2646,15 +2311,17 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
|||
priv->vif = vif;
|
||||
priv->iw_mode = vif->type;
|
||||
|
||||
if (vif->addr) {
|
||||
IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
|
||||
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
|
||||
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
if (iwl_set_mode(priv, vif->type) == -EAGAIN)
|
||||
/* we are not ready, will run again when ready */
|
||||
set_bit(STATUS_MODE_PENDING, &priv->status);
|
||||
err = iwl_set_mode(priv, vif);
|
||||
if (err)
|
||||
goto out_err;
|
||||
goto out;
|
||||
|
||||
out_err:
|
||||
priv->vif = NULL;
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
|
@ -2664,7 +2331,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
|||
EXPORT_SYMBOL(iwl_mac_add_interface);
|
||||
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
|
@ -2748,15 +2415,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
goto set_ch_out;
|
||||
}
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
|
||||
!is_channel_ibss(ch_info)) {
|
||||
IWL_ERR(priv, "channel %d in band %d not "
|
||||
"IBSS channel\n",
|
||||
conf->channel->hw_value, conf->channel->band);
|
||||
ret = -EINVAL;
|
||||
goto set_ch_out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Configure HT40 channels */
|
||||
|
@ -2878,8 +2536,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
|||
|
||||
priv->beacon_int = priv->vif->bss_conf.beacon_int;
|
||||
priv->timestamp = 0;
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_STATION))
|
||||
priv->beacon_int = 0;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
|
@ -2892,17 +2548,9 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
|||
/* we are restarting association process
|
||||
* clear RXON_FILTER_ASSOC_MSK bit
|
||||
*/
|
||||
if (priv->iw_mode != NL80211_IFTYPE_AP) {
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
}
|
||||
|
||||
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
||||
iwl_set_rate(priv);
|
||||
|
||||
|
|
|
@ -336,7 +336,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
u32 changes);
|
||||
int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int iwl_commit_rxon(struct iwl_priv *priv);
|
||||
int iwl_set_mode(struct iwl_priv *priv, int mode);
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
|
@ -560,11 +559,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
|
|||
* PCI *
|
||||
*****************************************************/
|
||||
irqreturn_t iwl_isr_legacy(int irq, void *data);
|
||||
int iwl_reset_ict(struct iwl_priv *priv);
|
||||
void iwl_disable_ict(struct iwl_priv *priv);
|
||||
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);
|
||||
|
||||
static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -622,7 +616,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
|
|||
#define STATUS_SCAN_HW 15
|
||||
#define STATUS_POWER_PMI 16
|
||||
#define STATUS_FW_ERROR 17
|
||||
#define STATUS_MODE_PENDING 18
|
||||
|
||||
|
||||
static inline int iwl_is_ready(struct iwl_priv *priv)
|
||||
|
@ -682,7 +675,6 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
|
|||
void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_stop_master(struct iwl_priv *priv);
|
||||
int iwl_apm_init(struct iwl_priv *priv);
|
||||
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv);
|
||||
|
|
|
@ -560,8 +560,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
|
|||
test_bit(STATUS_POWER_PMI, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
|
||||
test_bit(STATUS_FW_ERROR, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
|
||||
test_bit(STATUS_MODE_PENDING, &priv->status));
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
|
@ -660,7 +658,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
|
|||
int pos = 0, i;
|
||||
char buf[256];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
for (i = 0; i < AC_NUM; i++) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
|
@ -672,8 +669,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
|
|||
priv->qos_data.def_qos_parm.ac[i].aifsn,
|
||||
priv->qos_data.def_qos_parm.ac[i].edca_txop);
|
||||
}
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
|
||||
|
@ -683,7 +679,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
|
|||
int pos = 0;
|
||||
char buf[256];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"allow blinking: %s\n",
|
||||
|
@ -697,8 +692,7 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
|
|||
priv->last_blink_time);
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
|
||||
|
@ -711,7 +705,6 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
|
|||
char buf[100];
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"Thermal Throttling Mode: %s\n",
|
||||
|
@ -731,8 +724,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
|
|||
"HT mode: %d\n",
|
||||
restriction->is_ht);
|
||||
}
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
|
||||
|
@ -769,13 +761,11 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
|
|||
char buf[100];
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"11n 40MHz Mode: %s\n",
|
||||
priv->disable_ht40 ? "Disabled" : "Enabled");
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
|
||||
|
@ -2051,7 +2041,6 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
|
|||
int pos = 0;
|
||||
char buf[128];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
|
||||
priv->event_log.ucode_trace ? "On" : "Off");
|
||||
|
@ -2062,8 +2051,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
|
|||
pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
|
||||
priv->event_log.wraps_more_count);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
|
||||
|
@ -2095,6 +2083,31 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
int len = 0;
|
||||
char buf[20];
|
||||
|
||||
len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags));
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
int len = 0;
|
||||
char buf[20];
|
||||
|
||||
len = sprintf(buf, "0x%04X\n",
|
||||
le32_to_cpu(priv->active_rxon.filter_flags));
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -2124,13 +2137,11 @@ static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
|
|||
int pos = 0;
|
||||
char buf[12];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
|
||||
priv->missed_beacon_threshold);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
|
||||
|
@ -2159,27 +2170,6 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_internal_scan_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
char buf[8];
|
||||
int buf_size;
|
||||
int scan;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buf_size = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
if (sscanf(buf, "%d", &scan) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
iwl_internal_short_hw_scan(priv);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
@ -2188,13 +2178,11 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
|
|||
int pos = 0;
|
||||
char buf[12];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
ssize_t ret;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
|
||||
priv->cfg->plcp_delta_threshold);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
return ret;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
|
||||
|
@ -2295,9 +2283,10 @@ DEBUGFS_WRITE_FILE_OPS(csr);
|
|||
DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
|
||||
DEBUGFS_READ_FILE_OPS(fh_reg);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
|
||||
DEBUGFS_WRITE_FILE_OPS(internal_scan);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
|
||||
DEBUGFS_READ_FILE_OPS(rxon_flags);
|
||||
DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
|
@ -2349,7 +2338,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
|
@ -2360,6 +2348,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
|
||||
}
|
||||
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal);
|
||||
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
|
||||
&priv->disable_chain_noise_cal);
|
||||
|
|
|
@ -304,13 +304,11 @@ struct iwl_channel_info {
|
|||
struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
|
||||
};
|
||||
|
||||
#define IWL_TX_FIFO_AC0 0
|
||||
#define IWL_TX_FIFO_AC1 1
|
||||
#define IWL_TX_FIFO_AC2 2
|
||||
#define IWL_TX_FIFO_AC3 3
|
||||
#define IWL_TX_FIFO_HCCA_1 5
|
||||
#define IWL_TX_FIFO_HCCA_2 6
|
||||
#define IWL_TX_FIFO_NONE 7
|
||||
#define IWL_TX_FIFO_BK 0
|
||||
#define IWL_TX_FIFO_BE 1
|
||||
#define IWL_TX_FIFO_VI 2
|
||||
#define IWL_TX_FIFO_VO 3
|
||||
#define IWL_TX_FIFO_UNUSED -1
|
||||
|
||||
/* Minimum number of queues. MAX_NUM is defined in hw specific files.
|
||||
* Set the minimum to accommodate the 4 standard TX queues, 1 command
|
||||
|
@ -1092,10 +1090,6 @@ struct iwl_priv {
|
|||
struct iwl_channel_info *channel_info; /* channel info array */
|
||||
u8 channel_count; /* # of channels */
|
||||
|
||||
/* each calibration channel group in the EEPROM has a derived
|
||||
* clip setting for each rate. 3945 only.*/
|
||||
const struct iwl3945_clip_group clip39_groups[5];
|
||||
|
||||
/* thermal calibration */
|
||||
s32 temperature; /* degrees Kelvin */
|
||||
s32 last_temperature;
|
||||
|
@ -1168,7 +1162,6 @@ struct iwl_priv {
|
|||
u64 led_tpt;
|
||||
|
||||
u16 active_rate;
|
||||
u16 active_rate_basic;
|
||||
|
||||
u8 assoc_station_added;
|
||||
u8 start_calib;
|
||||
|
@ -1197,7 +1190,6 @@ struct iwl_priv {
|
|||
|
||||
unsigned long status;
|
||||
|
||||
int last_rx_rssi; /* From Rx packet statistics */
|
||||
int last_rx_noise; /* From beacon statistics */
|
||||
|
||||
/* counts mgmt, ctl, and data packets */
|
||||
|
@ -1218,8 +1210,6 @@ struct iwl_priv {
|
|||
#endif
|
||||
|
||||
/* context information */
|
||||
u16 rates_mask;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 rts_threshold;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
@ -1228,7 +1218,7 @@ struct iwl_priv {
|
|||
spinlock_t sta_lock;
|
||||
int num_stations;
|
||||
struct iwl_station_entry stations[IWL_STATION_COUNT];
|
||||
struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
|
||||
struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */
|
||||
u8 default_wep_key;
|
||||
u8 key_mapping_key;
|
||||
unsigned long ucode_key_table;
|
||||
|
@ -1244,10 +1234,6 @@ struct iwl_priv {
|
|||
|
||||
u8 mac80211_registered;
|
||||
|
||||
/* Rx'd packet timing information */
|
||||
u32 last_beacon_time;
|
||||
u64 last_tsf;
|
||||
|
||||
/* eeprom -- this is in the card's little endian byte order */
|
||||
u8 *eeprom;
|
||||
int nvm_device_type;
|
||||
|
@ -1262,20 +1248,48 @@ struct iwl_priv {
|
|||
u16 beacon_int;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
/*Added for 3945 */
|
||||
void *shared_virt;
|
||||
dma_addr_t shared_phys;
|
||||
/*End*/
|
||||
struct iwl_hw_params hw_params;
|
||||
union {
|
||||
#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
|
||||
struct {
|
||||
void *shared_virt;
|
||||
dma_addr_t shared_phys;
|
||||
|
||||
/* INT ICT Table */
|
||||
__le32 *ict_tbl;
|
||||
dma_addr_t ict_tbl_dma;
|
||||
dma_addr_t aligned_ict_tbl_dma;
|
||||
int ict_index;
|
||||
void *ict_tbl_vir;
|
||||
u32 inta;
|
||||
bool use_ict;
|
||||
struct delayed_work thermal_periodic;
|
||||
struct delayed_work rfkill_poll;
|
||||
|
||||
struct iwl3945_notif_statistics statistics;
|
||||
|
||||
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
|
||||
#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;
|
||||
} _agn;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct iwl_hw_params hw_params;
|
||||
|
||||
u32 inta_mask;
|
||||
/* Current association information needed to configure the
|
||||
|
@ -1303,10 +1317,6 @@ struct iwl_priv {
|
|||
struct delayed_work alive_start;
|
||||
struct delayed_work scan_check;
|
||||
|
||||
/*For 3945 only*/
|
||||
struct delayed_work thermal_periodic;
|
||||
struct delayed_work rfkill_poll;
|
||||
|
||||
/* TX Power */
|
||||
s8 tx_power_user_lmt;
|
||||
s8 tx_power_device_lmt;
|
||||
|
@ -1339,12 +1349,6 @@ struct iwl_priv {
|
|||
struct timer_list statistics_periodic;
|
||||
struct timer_list ucode_trace;
|
||||
bool hw_ready;
|
||||
/*For 3945*/
|
||||
#define IWL_DEFAULT_TX_POWER 0x0F
|
||||
|
||||
struct iwl3945_notif_statistics statistics_39;
|
||||
|
||||
u32 sta_supp_rates;
|
||||
|
||||
struct iwl_event_log event_log;
|
||||
}; /*iwl_priv */
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#define __iwl_helpers_h__
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-io.h"
|
||||
|
||||
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@
|
|||
* 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 channels have dedicated purposes. For 4965, they are used as follows
|
||||
* 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
|
||||
|
@ -262,20 +262,20 @@
|
|||
* 2 -- EDCA VI (video) frames, higher priority
|
||||
* 3 -- EDCA VO (voice) and management frames, highest priority
|
||||
* 4 -- Commands (e.g. RXON, etc.)
|
||||
* 5 -- HCCA short frames
|
||||
* 6 -- HCCA long frames
|
||||
* 5 -- unused (HCCA)
|
||||
* 6 -- unused (HCCA)
|
||||
* 7 -- not used by driver (device-internal only)
|
||||
*
|
||||
* For 5000 series and up, they are used slightly differently
|
||||
* For 5000 series and up, they are used differently
|
||||
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.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 -- (TBD)
|
||||
* 5 -- HCCA short frames
|
||||
* 6 -- HCCA long frames
|
||||
* 4 -- unused
|
||||
* 5 -- unused
|
||||
* 6 -- unused
|
||||
* 7 -- Commands
|
||||
*
|
||||
* Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
|
||||
|
|
|
@ -1036,24 +1036,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|||
rxb->page = NULL;
|
||||
}
|
||||
|
||||
/* This is necessary only for a number of statistics, see the caller. */
|
||||
static int iwl_is_network_packet(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *header)
|
||||
{
|
||||
/* Filter incoming packets to determine if they are targeted toward
|
||||
* this network, discarding packets coming from ourselves */
|
||||
switch (priv->iw_mode) {
|
||||
case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */
|
||||
/* packets to our IBSS update information */
|
||||
return !compare_ether_addr(header->addr3, priv->bssid);
|
||||
case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
|
||||
/* packets to our IBSS update information */
|
||||
return !compare_ether_addr(header->addr2, priv->bssid);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called for REPLY_RX (legacy ABG frames), or
|
||||
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
|
||||
void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
|
@ -1190,12 +1172,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
|||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORT_GI;
|
||||
|
||||
if (iwl_is_network_packet(priv, header)) {
|
||||
priv->last_rx_rssi = rx_status.signal;
|
||||
priv->last_beacon_time = priv->ucode_beacon_time;
|
||||
priv->last_tsf = le64_to_cpu(phy_res->timestamp);
|
||||
}
|
||||
|
||||
iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
|
||||
rxb, &rx_status);
|
||||
}
|
||||
|
|
|
@ -580,7 +580,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_internal_short_hw_scan);
|
||||
|
||||
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
|
||||
|
||||
|
@ -665,7 +664,6 @@ static void iwl_bg_request_scan(struct work_struct *data)
|
|||
};
|
||||
struct iwl_scan_cmd *scan;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
u32 rate_flags = 0;
|
||||
u16 cmd_len;
|
||||
u16 rx_chain = 0;
|
||||
|
@ -698,7 +696,6 @@ static void iwl_bg_request_scan(struct work_struct *data)
|
|||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
|
||||
"Ignoring second request.\n");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -731,7 +728,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
|
|||
priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
|
||||
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
|
||||
if (!priv->scan) {
|
||||
ret = -ENOMEM;
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"fail to allocate memory for scan\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@ -892,8 +890,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
|
|||
scan->len = cpu_to_le16(cmd.len);
|
||||
|
||||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
ret = iwl_send_cmd_sync(priv, &cmd);
|
||||
if (ret)
|
||||
if (iwl_send_cmd_sync(priv, &cmd))
|
||||
goto done;
|
||||
|
||||
queue_delayed_work(priv->workqueue, &priv->scan_check,
|
||||
|
|
|
@ -549,9 +549,11 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
|||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_WEPKEY,
|
||||
.data = wep_cmd,
|
||||
.flags = CMD_ASYNC,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
might_sleep();
|
||||
|
||||
memset(wep_cmd, 0, cmd_size +
|
||||
(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
|
||||
|
||||
|
@ -587,9 +589,9 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
|||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
WARN_ON(!mutex_is_locked(&priv->mutex));
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
|
||||
keyconf->keyidx);
|
||||
|
||||
|
@ -601,13 +603,12 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
|||
memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
/* but keys in device are clear anyway so return success */
|
||||
return 0;
|
||||
}
|
||||
ret = iwl_send_static_wepkey_cmd(priv, 1);
|
||||
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
|
||||
keyconf->keyidx, ret);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -617,7 +618,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
|
|||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&priv->mutex));
|
||||
|
||||
if (keyconf->keylen != WEP_KEY_LEN_128 &&
|
||||
keyconf->keylen != WEP_KEY_LEN_64) {
|
||||
|
@ -629,12 +631,11 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
|
|||
keyconf->hw_key_idx = HW_KEY_DEFAULT;
|
||||
priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->default_wep_key++;
|
||||
|
||||
if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
|
||||
IWL_ERR(priv, "index %d already used in uCode key table.\n",
|
||||
keyconf->keyidx);
|
||||
keyconf->keyidx);
|
||||
|
||||
priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
|
||||
memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
|
||||
|
@ -643,7 +644,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
|
|||
ret = iwl_send_static_wepkey_cmd(priv, 0);
|
||||
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
|
||||
keyconf->keylen, keyconf->keyidx, ret);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,26 +37,63 @@
|
|||
#include "iwl-io.h"
|
||||
#include "iwl-helpers.h"
|
||||
|
||||
static const u16 default_tid_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_AC1,
|
||||
IWL_TX_FIFO_AC0,
|
||||
IWL_TX_FIFO_AC0,
|
||||
IWL_TX_FIFO_AC1,
|
||||
IWL_TX_FIFO_AC2,
|
||||
IWL_TX_FIFO_AC2,
|
||||
IWL_TX_FIFO_AC3,
|
||||
IWL_TX_FIFO_AC3,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_NONE,
|
||||
IWL_TX_FIFO_AC3
|
||||
/*
|
||||
* mac80211 queues, ACs, hardware queues, FIFOs.
|
||||
*
|
||||
* Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
|
||||
*
|
||||
* Mac80211 uses the following numbers, which we get as from it
|
||||
* by way of skb_get_queue_mapping(skb):
|
||||
*
|
||||
* VO 0
|
||||
* VI 1
|
||||
* BE 2
|
||||
* BK 3
|
||||
*
|
||||
*
|
||||
* Regular (not A-MPDU) frames are put into hardware queues corresponding
|
||||
* to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
|
||||
* own queue per aggregation session (RA/TID combination), such queues are
|
||||
* set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
|
||||
* order to map frames to the right queue, we also need an AC->hw queue
|
||||
* mapping. This is implemented here.
|
||||
*
|
||||
* Due to the way hw queues are set up (by the hw specific modules like
|
||||
* iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
|
||||
* mapping.
|
||||
*/
|
||||
|
||||
static const u8 tid_to_ac[] = {
|
||||
/* this matches the mac80211 numbers */
|
||||
2, 3, 3, 2, 1, 1, 0, 0
|
||||
};
|
||||
|
||||
static const u8 ac_to_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
IWL_TX_FIFO_VI,
|
||||
IWL_TX_FIFO_BE,
|
||||
IWL_TX_FIFO_BK,
|
||||
};
|
||||
|
||||
static inline int get_fifo_from_ac(u8 ac)
|
||||
{
|
||||
return ac_to_fifo[ac];
|
||||
}
|
||||
|
||||
static inline int get_queue_from_ac(u16 ac)
|
||||
{
|
||||
return ac;
|
||||
}
|
||||
|
||||
static inline int get_fifo_from_tid(u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
return get_fifo_from_ac(tid_to_ac[tid]);
|
||||
|
||||
/* no support for TIDs 8-15 yet */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
|
||||
struct iwl_dma_ptr *ptr, size_t size)
|
||||
{
|
||||
|
@ -591,13 +628,12 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
|
|||
tx_cmd->next_frame_len = 0;
|
||||
}
|
||||
|
||||
#define RTS_HCCA_RETRY_LIMIT 3
|
||||
#define RTS_DFAULT_RETRY_LIMIT 60
|
||||
|
||||
static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct ieee80211_tx_info *info,
|
||||
__le16 fc, int is_hcca)
|
||||
__le16 fc)
|
||||
{
|
||||
u32 rate_flags;
|
||||
int rate_idx;
|
||||
|
@ -613,8 +649,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||
tx_cmd->data_retry_limit = data_retry_limit;
|
||||
|
||||
/* Set retry limit on RTS packets */
|
||||
rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT :
|
||||
RTS_DFAULT_RETRY_LIMIT;
|
||||
rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
|
||||
if (data_retry_limit < rts_retry_limit)
|
||||
rts_retry_limit = data_retry_limit;
|
||||
tx_cmd->rts_retry_limit = rts_retry_limit;
|
||||
|
@ -761,16 +796,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
|
||||
#endif
|
||||
|
||||
/* drop all non-injected data frame if we are not associated */
|
||||
if (ieee80211_is_data(fc) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
||||
(!iwl_is_associated(priv) ||
|
||||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
|
||||
!priv->assoc_station_added)) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find (or create) index into station table for destination station */
|
||||
|
@ -804,7 +829,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
|
||||
}
|
||||
|
||||
txq_id = skb_get_queue_mapping(skb);
|
||||
txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
@ -869,8 +894,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
|
||||
iwl_dbg_log_tx_data_frame(priv, len, hdr);
|
||||
|
||||
/* set is_hcca to 0; it probably will never be implemented */
|
||||
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0);
|
||||
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc);
|
||||
|
||||
iwl_update_stats(priv, true, fc, len);
|
||||
/*
|
||||
|
@ -1270,7 +1294,7 @@ EXPORT_SYMBOL(iwl_tx_cmd_complete);
|
|||
* Find first available (lowest unused) Tx Queue, mark it "active".
|
||||
* Called only when finding queue for aggregation.
|
||||
* Should never return anything < 7, because they should already
|
||||
* be in use as EDCA AC (0-3), Command (4), HCCA (5, 6).
|
||||
* be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
|
||||
*/
|
||||
static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -1291,10 +1315,9 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
|
|||
unsigned long flags;
|
||||
struct iwl_tid_data *tid_data;
|
||||
|
||||
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
|
||||
tx_fifo = default_tid_to_tx_fifo[tid];
|
||||
else
|
||||
return -EINVAL;
|
||||
tx_fifo = get_fifo_from_tid(tid);
|
||||
if (unlikely(tx_fifo < 0))
|
||||
return tx_fifo;
|
||||
|
||||
IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
|
||||
__func__, ra, tid);
|
||||
|
@ -1355,13 +1378,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely(tid >= MAX_TID_COUNT))
|
||||
return -EINVAL;
|
||||
|
||||
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
|
||||
tx_fifo_id = default_tid_to_tx_fifo[tid];
|
||||
else
|
||||
return -EINVAL;
|
||||
tx_fifo_id = get_fifo_from_tid(tid);
|
||||
if (unlikely(tx_fifo_id < 0))
|
||||
return tx_fifo_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, ra);
|
||||
|
||||
|
@ -1429,7 +1448,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
|
|||
if ((txq_id == tid_data->agg.txq_id) &&
|
||||
(q->read_ptr == q->write_ptr)) {
|
||||
u16 ssn = SEQ_TO_SN(tid_data->seq_number);
|
||||
int tx_fifo = default_tid_to_tx_fifo[tid];
|
||||
int tx_fifo = get_fifo_from_tid(tid);
|
||||
IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
|
||||
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
|
||||
ssn, tx_fifo);
|
||||
|
|
|
@ -351,11 +351,11 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
|
|||
|
||||
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->shared_virt)
|
||||
if (priv->_3945.shared_virt)
|
||||
dma_free_coherent(&priv->pci_dev->dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
priv->shared_virt,
|
||||
priv->shared_phys);
|
||||
priv->_3945.shared_virt,
|
||||
priv->_3945.shared_phys);
|
||||
}
|
||||
|
||||
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
|
||||
|
@ -504,15 +504,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
|
||||
#endif
|
||||
|
||||
/* drop all non-injected data frame if we are not associated */
|
||||
if (ieee80211_is_data(fc) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
||||
(!iwl_is_associated(priv) ||
|
||||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
@ -753,7 +744,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
if (iwl_is_associated(priv))
|
||||
add_time =
|
||||
iwl3945_usecs_to_beacons(
|
||||
le64_to_cpu(params->start_time) - priv->last_tsf,
|
||||
le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
|
||||
le16_to_cpu(priv->rxon_timing.beacon_interval));
|
||||
|
||||
memset(&spectrum, 0, sizeof(spectrum));
|
||||
|
@ -767,7 +758,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
|
||||
if (iwl_is_associated(priv))
|
||||
spectrum.start_time =
|
||||
iwl3945_add_beacon_time(priv->last_beacon_time,
|
||||
iwl3945_add_beacon_time(priv->_3945.last_beacon_time,
|
||||
add_time,
|
||||
le16_to_cpu(priv->rxon_timing.beacon_interval));
|
||||
else
|
||||
|
@ -2517,8 +2508,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
|||
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
|
||||
priv->active_rate = priv->rates_mask;
|
||||
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
|
||||
priv->active_rate = IWL_RATES_MASK;
|
||||
|
||||
iwl_power_update_mode(priv, true);
|
||||
|
||||
|
@ -2547,17 +2537,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
|||
set_bit(STATUS_READY, &priv->status);
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
|
||||
/* reassociate for ADHOC mode */
|
||||
if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
|
||||
priv->vif);
|
||||
if (beacon)
|
||||
iwl_mac_beacon_update(priv->hw, beacon);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
|
||||
iwl_set_mode(priv, priv->iw_mode);
|
||||
|
||||
return;
|
||||
|
||||
restart:
|
||||
|
@ -2718,7 +2697,7 @@ static int __iwl3945_up(struct iwl_priv *priv)
|
|||
/* load bootstrap state machine,
|
||||
* load bootstrap program into processor's memory,
|
||||
* prepare to load the "initialize" uCode */
|
||||
priv->cfg->ops->lib->load_ucode(priv);
|
||||
rc = priv->cfg->ops->lib->load_ucode(priv);
|
||||
|
||||
if (rc) {
|
||||
IWL_ERR(priv,
|
||||
|
@ -2786,7 +2765,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
|
|||
static void iwl3945_rfkill_poll(struct work_struct *data)
|
||||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(data, struct iwl_priv, rfkill_poll.work);
|
||||
container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
|
||||
bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
|
||||
& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
|
@ -2805,7 +2784,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
|
|||
|
||||
/* Keep this running, even if radio now enabled. This will be
|
||||
* cancelled in mac_start() if system decides to start again */
|
||||
queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
|
||||
queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
|
||||
round_jiffies_relative(2 * HZ));
|
||||
|
||||
}
|
||||
|
@ -2820,7 +2799,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
|
|||
.len = sizeof(struct iwl3945_scan_cmd),
|
||||
.flags = CMD_SIZE_HUGE,
|
||||
};
|
||||
int rc = 0;
|
||||
struct iwl3945_scan_cmd *scan;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
u8 n_probes = 0;
|
||||
|
@ -2848,7 +2826,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
|
|||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests "
|
||||
"Ignoring second request.\n");
|
||||
rc = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -2883,7 +2860,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
|
|||
priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
|
||||
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
|
||||
if (!priv->scan) {
|
||||
rc = -ENOMEM;
|
||||
IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@ -2926,7 +2903,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
|
|||
scan_suspend_time, interval);
|
||||
}
|
||||
|
||||
if (priv->scan_request->n_ssids) {
|
||||
if (priv->is_internal_short_scan) {
|
||||
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
|
||||
} else if (priv->scan_request->n_ssids) {
|
||||
int i, p = 0;
|
||||
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
|
||||
for (i = 0; i < priv->scan_request->n_ssids; i++) {
|
||||
|
@ -2973,13 +2952,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
|
|||
goto done;
|
||||
}
|
||||
|
||||
scan->tx_cmd.len = cpu_to_le16(
|
||||
if (!priv->is_internal_short_scan) {
|
||||
scan->tx_cmd.len = cpu_to_le16(
|
||||
iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
priv->scan_request->ie,
|
||||
priv->scan_request->ie_len,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
|
||||
|
||||
} else {
|
||||
scan->tx_cmd.len = cpu_to_le16(
|
||||
iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
|
||||
}
|
||||
/* select Rx antennas */
|
||||
scan->flags |= iwl3945_get_antenna_flags(priv);
|
||||
|
||||
|
@ -3001,8 +2987,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
|
|||
scan->len = cpu_to_le16(cmd.len);
|
||||
|
||||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
rc = iwl_send_cmd_sync(priv, &cmd);
|
||||
if (rc)
|
||||
if (iwl_send_cmd_sync(priv, &cmd))
|
||||
goto done;
|
||||
|
||||
queue_delayed_work(priv->workqueue, &priv->scan_check,
|
||||
|
@ -3212,7 +3197,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
|
|||
|
||||
/* ucode is running and will send rfkill notifications,
|
||||
* no need to poll the killswitch state anymore */
|
||||
cancel_delayed_work(&priv->rfkill_poll);
|
||||
cancel_delayed_work(&priv->_3945.rfkill_poll);
|
||||
|
||||
iwl_led_start(priv);
|
||||
|
||||
|
@ -3253,7 +3238,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
|
|||
flush_workqueue(priv->workqueue);
|
||||
|
||||
/* start polling the killswitch state again */
|
||||
queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
|
||||
queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
|
||||
round_jiffies_relative(2 * HZ));
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
@ -3365,7 +3350,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
|
@ -3386,6 +3370,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
|
@ -3590,7 +3575,7 @@ static ssize_t store_measurement(struct device *d,
|
|||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
struct ieee80211_measurement_params params = {
|
||||
.channel = le16_to_cpu(priv->active_rxon.channel),
|
||||
.start_time = cpu_to_le64(priv->last_tsf),
|
||||
.start_time = cpu_to_le64(priv->_3945.last_tsf),
|
||||
.duration = cpu_to_le16(1),
|
||||
};
|
||||
u8 type = IWL_MEASURE_BASIC;
|
||||
|
@ -3660,7 +3645,7 @@ static ssize_t show_statistics(struct device *d,
|
|||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
u32 size = sizeof(struct iwl3945_notif_statistics);
|
||||
u32 len = 0, ofs = 0;
|
||||
u8 *data = (u8 *)&priv->statistics_39;
|
||||
u8 *data = (u8 *)&priv->_3945.statistics;
|
||||
int rc = 0;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
|
@ -3773,7 +3758,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
|
|||
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
|
||||
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
|
||||
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
|
||||
INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll);
|
||||
INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
|
||||
INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
|
||||
INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
|
||||
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
|
||||
|
@ -3864,7 +3849,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
|
|||
priv->qos_data.qos_active = 0;
|
||||
priv->qos_data.qos_cap.val = 0;
|
||||
|
||||
priv->rates_mask = IWL_RATES_MASK;
|
||||
priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
|
||||
|
||||
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
|
||||
|
@ -4129,7 +4113,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
|
||||
|
||||
/* Start monitoring the killswitch */
|
||||
queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
|
||||
queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
|
||||
2 * HZ);
|
||||
|
||||
return 0;
|
||||
|
@ -4203,7 +4187,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
|
|||
|
||||
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
|
||||
|
||||
cancel_delayed_work_sync(&priv->rfkill_poll);
|
||||
cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
|
||||
|
||||
iwl3945_dealloc_ucode_pci(priv);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ config IWM
|
|||
config IWM_DEBUG
|
||||
bool "Enable full debugging output in iwmc3200wifi"
|
||||
depends on IWM && DEBUG_FS
|
||||
---help---
|
||||
help
|
||||
This option will enable debug tracing and setting for iwm
|
||||
|
||||
You can set the debug level and module through debugfs. By
|
||||
|
@ -30,3 +30,10 @@ config IWM_DEBUG
|
|||
Or, if you want the full debug, for all modules:
|
||||
echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level
|
||||
echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules
|
||||
|
||||
config IWM_TRACING
|
||||
bool "Enable event tracing for iwmc3200wifi"
|
||||
depends on IWM && EVENT_TRACING
|
||||
help
|
||||
Say Y here to trace all the commands and responses between
|
||||
the driver and firmware (including TX/RX frames) with ftrace.
|
||||
|
|
|
@ -3,3 +3,6 @@ iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
|
|||
iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o
|
||||
|
||||
iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
|
||||
iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o
|
||||
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
|
|
@ -263,7 +263,7 @@ static int iwm_cfg80211_get_station(struct wiphy *wiphy,
|
|||
int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
|
||||
{
|
||||
struct wiphy *wiphy = iwm_to_wiphy(iwm);
|
||||
struct iwm_bss_info *bss, *next;
|
||||
struct iwm_bss_info *bss;
|
||||
struct iwm_umac_notif_bss_info *umac_bss;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ieee80211_channel *channel;
|
||||
|
@ -271,7 +271,7 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
|
|||
s32 signal;
|
||||
int freq;
|
||||
|
||||
list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
|
||||
list_for_each_entry(bss, &iwm->bss_list, node) {
|
||||
umac_bss = bss->bss;
|
||||
mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
|
||||
|
||||
|
@ -725,23 +725,26 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
|
|||
CFG_POWER_INDEX, iwm->conf.power_index);
|
||||
}
|
||||
|
||||
int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa)
|
||||
static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
|
||||
struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa)
|
||||
{
|
||||
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
|
||||
|
||||
return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
|
||||
}
|
||||
|
||||
int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa)
|
||||
static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
|
||||
struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa)
|
||||
{
|
||||
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
|
||||
|
||||
return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
|
||||
}
|
||||
|
||||
int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
|
||||
static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
|
||||
struct net_device *netdev)
|
||||
{
|
||||
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
|
||||
struct cfg80211_pmksa pmksa;
|
||||
|
|
|
@ -506,7 +506,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* When succeding, the send_target routine returns the seq number */
|
||||
/* When succeeding, the send_target routine returns the seq number */
|
||||
seq_num = ret;
|
||||
|
||||
ret = wait_event_interruptible_timeout(iwm->nonwifi_queue,
|
||||
|
@ -781,10 +781,9 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
|
||||
int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
|
||||
{
|
||||
struct iwm_umac_invalidate_profile invalid;
|
||||
int ret;
|
||||
|
||||
invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
|
||||
invalid.hdr.buf_size =
|
||||
|
@ -793,7 +792,14 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
|
|||
|
||||
invalid.reason = WLAN_REASON_UNSPECIFIED;
|
||||
|
||||
ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
|
||||
return iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
|
||||
}
|
||||
|
||||
int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = __iwm_invalidate_mlme_profile(iwm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -488,6 +488,7 @@ int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
|
|||
void *payload, u16 payload_size);
|
||||
int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags);
|
||||
int iwm_send_mlme_profile(struct iwm_priv *iwm);
|
||||
int __iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
|
||||
int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
|
||||
int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
|
||||
int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
|
||||
|
|
|
@ -265,7 +265,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwm_priv *iwm = filp->private_data;
|
||||
struct iwm_rx_ticket_node *ticket, *next;
|
||||
struct iwm_rx_ticket_node *ticket;
|
||||
char *buf;
|
||||
int buf_len = 4096, i;
|
||||
size_t len = 0;
|
||||
|
@ -280,7 +280,8 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
|
|||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
|
||||
spin_lock(&iwm->ticket_lock);
|
||||
list_for_each_entry(ticket, &iwm->rx_tickets, node) {
|
||||
len += snprintf(buf + len, buf_len - len, "Ticket #%d\n",
|
||||
ticket->ticket->id);
|
||||
len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n",
|
||||
|
@ -288,14 +289,17 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
|
|||
len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n",
|
||||
ticket->ticket->flags);
|
||||
}
|
||||
spin_unlock(&iwm->ticket_lock);
|
||||
|
||||
for (i = 0; i < IWM_RX_ID_HASH; i++) {
|
||||
struct iwm_rx_packet *packet, *nxt;
|
||||
struct iwm_rx_packet *packet;
|
||||
struct list_head *pkt_list = &iwm->rx_packets[i];
|
||||
|
||||
if (!list_empty(pkt_list)) {
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"Packet hash #%d\n", i);
|
||||
list_for_each_entry_safe(packet, nxt, pkt_list, node) {
|
||||
spin_lock(&iwm->packet_lock[i]);
|
||||
list_for_each_entry(packet, pkt_list, node) {
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tPacket id: %d\n",
|
||||
packet->id);
|
||||
|
@ -303,6 +307,7 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
|
|||
"\tPacket length: %lu\n",
|
||||
packet->pkt_size);
|
||||
}
|
||||
spin_unlock(&iwm->packet_lock[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
#include "hal.h"
|
||||
#include "umac.h"
|
||||
#include "debug.h"
|
||||
#include "trace.h"
|
||||
|
||||
static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
|
||||
struct iwm_nonwifi_cmd *cmd,
|
||||
|
@ -206,9 +207,9 @@ void iwm_cmd_flush(struct iwm_priv *iwm)
|
|||
|
||||
struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num)
|
||||
{
|
||||
struct iwm_wifi_cmd *cmd, *next;
|
||||
struct iwm_wifi_cmd *cmd;
|
||||
|
||||
list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending)
|
||||
list_for_each_entry(cmd, &iwm->wifi_pending_cmd, pending)
|
||||
if (cmd->seq_num == seq_num) {
|
||||
list_del(&cmd->pending);
|
||||
return cmd;
|
||||
|
@ -217,12 +218,12 @@ struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct iwm_nonwifi_cmd *
|
||||
iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode)
|
||||
struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
|
||||
u8 seq_num, u8 cmd_opcode)
|
||||
{
|
||||
struct iwm_nonwifi_cmd *cmd, *next;
|
||||
struct iwm_nonwifi_cmd *cmd;
|
||||
|
||||
list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending)
|
||||
list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
|
||||
if ((cmd->seq_num == seq_num) &&
|
||||
(cmd->udma_cmd.opcode == cmd_opcode) &&
|
||||
(cmd->resp_received)) {
|
||||
|
@ -276,6 +277,7 @@ static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm,
|
|||
udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr,
|
||||
udma_cmd->op1_sz, udma_cmd->op2);
|
||||
|
||||
trace_iwm_tx_nonwifi_cmd(iwm, udma_hdr);
|
||||
return iwm_bus_send_chunk(iwm, buf->start, buf->len);
|
||||
}
|
||||
|
||||
|
@ -362,6 +364,7 @@ static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
trace_iwm_tx_wifi_cmd(iwm, umac_hdr);
|
||||
return iwm_bus_send_chunk(iwm, buf->start, buf->len);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ do { \
|
|||
|
||||
|
||||
/* UDMA IN OP CODE -- cmd bits [3:0] */
|
||||
#define UDMA_IN_OPCODE_MASK 0xF
|
||||
#define UDMA_HDI_IN_NW_CMD_OPCODE_POS 0
|
||||
#define UDMA_HDI_IN_NW_CMD_OPCODE_SEED 0xF
|
||||
|
||||
#define UDMA_IN_OPCODE_GENERAL_RESP 0x0
|
||||
#define UDMA_IN_OPCODE_READ_RESP 0x1
|
||||
|
@ -130,7 +131,7 @@ do { \
|
|||
#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
|
||||
IWM_MAX_WIFI_HEADERS_SIZE)
|
||||
|
||||
#define IWM_HAL_CONCATENATE_BUF_SIZE 8192
|
||||
#define IWM_HAL_CONCATENATE_BUF_SIZE (32 * 1024)
|
||||
|
||||
struct iwm_wifi_cmd_buff {
|
||||
u16 len;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "umac.h"
|
||||
#include "lmac.h"
|
||||
#include "eeprom.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
|
||||
#define IWM_AUTHOR "<ilw@linux.intel.com>"
|
||||
|
@ -268,7 +269,9 @@ struct iwm_priv {
|
|||
|
||||
struct sk_buff_head rx_list;
|
||||
struct list_head rx_tickets;
|
||||
spinlock_t ticket_lock;
|
||||
struct list_head rx_packets[IWM_RX_ID_HASH];
|
||||
spinlock_t packet_lock[IWM_RX_ID_HASH];
|
||||
struct workqueue_struct *rx_wq;
|
||||
struct work_struct rx_worker;
|
||||
|
||||
|
|
|
@ -276,8 +276,11 @@ int iwm_priv_init(struct iwm_priv *iwm)
|
|||
|
||||
skb_queue_head_init(&iwm->rx_list);
|
||||
INIT_LIST_HEAD(&iwm->rx_tickets);
|
||||
for (i = 0; i < IWM_RX_ID_HASH; i++)
|
||||
spin_lock_init(&iwm->ticket_lock);
|
||||
for (i = 0; i < IWM_RX_ID_HASH; i++) {
|
||||
INIT_LIST_HEAD(&iwm->rx_packets[i]);
|
||||
spin_lock_init(&iwm->packet_lock[i]);
|
||||
}
|
||||
|
||||
INIT_WORK(&iwm->rx_worker, iwm_rx_worker);
|
||||
|
||||
|
@ -423,9 +426,9 @@ int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
|
|||
static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd,
|
||||
u8 source)
|
||||
{
|
||||
struct iwm_notif *notif, *next;
|
||||
struct iwm_notif *notif;
|
||||
|
||||
list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
|
||||
list_for_each_entry(notif, &iwm->pending_notif, pending) {
|
||||
if ((notif->cmd_id == cmd) && (notif->src == source)) {
|
||||
list_del(¬if->pending);
|
||||
return notif;
|
||||
|
|
|
@ -342,15 +342,17 @@ static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
|
|||
static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
|
||||
{
|
||||
u8 id_hash = IWM_RX_ID_GET_HASH(id);
|
||||
struct list_head *packet_list;
|
||||
struct iwm_rx_packet *packet, *next;
|
||||
struct iwm_rx_packet *packet;
|
||||
|
||||
packet_list = &iwm->rx_packets[id_hash];
|
||||
|
||||
list_for_each_entry_safe(packet, next, packet_list, node)
|
||||
if (packet->id == id)
|
||||
spin_lock(&iwm->packet_lock[id_hash]);
|
||||
list_for_each_entry(packet, &iwm->rx_packets[id_hash], node)
|
||||
if (packet->id == id) {
|
||||
list_del(&packet->node);
|
||||
spin_unlock(&iwm->packet_lock[id_hash]);
|
||||
return packet;
|
||||
}
|
||||
|
||||
spin_unlock(&iwm->packet_lock[id_hash]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -388,18 +390,22 @@ void iwm_rx_free(struct iwm_priv *iwm)
|
|||
struct iwm_rx_packet *packet, *np;
|
||||
int i;
|
||||
|
||||
spin_lock(&iwm->ticket_lock);
|
||||
list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
|
||||
list_del(&ticket->node);
|
||||
iwm_rx_ticket_node_free(ticket);
|
||||
}
|
||||
spin_unlock(&iwm->ticket_lock);
|
||||
|
||||
for (i = 0; i < IWM_RX_ID_HASH; i++) {
|
||||
spin_lock(&iwm->packet_lock[i]);
|
||||
list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
|
||||
node) {
|
||||
list_del(&packet->node);
|
||||
kfree_skb(packet->skb);
|
||||
kfree(packet);
|
||||
}
|
||||
spin_unlock(&iwm->packet_lock[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,7 +433,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
|
|||
ticket->action == IWM_RX_TICKET_RELEASE ?
|
||||
"RELEASE" : "DROP",
|
||||
ticket->id);
|
||||
spin_lock(&iwm->ticket_lock);
|
||||
list_add_tail(&ticket_node->node, &iwm->rx_tickets);
|
||||
spin_unlock(&iwm->ticket_lock);
|
||||
|
||||
/*
|
||||
* We received an Rx ticket, most likely there's
|
||||
|
@ -460,6 +468,7 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
|
|||
struct iwm_rx_packet *packet;
|
||||
u16 id, buf_offset;
|
||||
u32 packet_size;
|
||||
u8 id_hash;
|
||||
|
||||
IWM_DBG_RX(iwm, DBG, "\n");
|
||||
|
||||
|
@ -477,7 +486,10 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
|
|||
if (IS_ERR(packet))
|
||||
return PTR_ERR(packet);
|
||||
|
||||
list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]);
|
||||
id_hash = IWM_RX_ID_GET_HASH(id);
|
||||
spin_lock(&iwm->packet_lock[id_hash]);
|
||||
list_add_tail(&packet->node, &iwm->rx_packets[id_hash]);
|
||||
spin_unlock(&iwm->packet_lock[id_hash]);
|
||||
|
||||
/* We might (unlikely) have received the packet _after_ the ticket */
|
||||
queue_work(iwm->rx_wq, &iwm->rx_worker);
|
||||
|
@ -518,6 +530,8 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
|
|||
unsigned long buf_size,
|
||||
struct iwm_wifi_cmd *cmd)
|
||||
{
|
||||
struct wiphy *wiphy = iwm_to_wiphy(iwm);
|
||||
struct ieee80211_channel *chan;
|
||||
struct iwm_umac_notif_assoc_complete *complete =
|
||||
(struct iwm_umac_notif_assoc_complete *)buf;
|
||||
|
||||
|
@ -526,6 +540,18 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
|
|||
|
||||
switch (le32_to_cpu(complete->status)) {
|
||||
case UMAC_ASSOC_COMPLETE_SUCCESS:
|
||||
chan = ieee80211_get_channel(wiphy,
|
||||
ieee80211_channel_to_frequency(complete->channel));
|
||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
|
||||
/* Associated to a unallowed channel, disassociate. */
|
||||
__iwm_invalidate_mlme_profile(iwm);
|
||||
IWM_WARN(iwm, "Couldn't associate with %pM due to "
|
||||
"channel %d is disabled. Check your local "
|
||||
"regulatory setting.\n",
|
||||
complete->bssid, complete->channel);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
|
||||
memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
|
||||
iwm->channel = complete->channel;
|
||||
|
@ -562,6 +588,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
|
|||
GFP_KERNEL);
|
||||
break;
|
||||
case UMAC_ASSOC_COMPLETE_FAILURE:
|
||||
failure:
|
||||
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
|
||||
memset(iwm->bssid, 0, ETH_ALEN);
|
||||
iwm->channel = 0;
|
||||
|
@ -756,7 +783,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
|
|||
(struct iwm_umac_notif_bss_info *)buf;
|
||||
struct ieee80211_channel *channel;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct iwm_bss_info *bss, *next;
|
||||
struct iwm_bss_info *bss;
|
||||
s32 signal;
|
||||
int freq;
|
||||
u16 frame_len = le16_to_cpu(umac_bss->frame_len);
|
||||
|
@ -775,7 +802,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
|
|||
IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
|
||||
IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
|
||||
|
||||
list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
|
||||
list_for_each_entry(bss, &iwm->bss_list, node)
|
||||
if (bss->bss->table_idx == umac_bss->table_idx)
|
||||
break;
|
||||
|
||||
|
@ -842,16 +869,15 @@ static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
|
||||
table_idx = (le16_to_cpu(bss_rm->entries[i])
|
||||
& IWM_BSS_REMOVE_INDEX_MSK);
|
||||
table_idx = le16_to_cpu(bss_rm->entries[i]) &
|
||||
IWM_BSS_REMOVE_INDEX_MSK;
|
||||
list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
|
||||
if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *)
|
||||
(bss->bss->frame_buf);
|
||||
IWM_DBG_MLME(iwm, ERR,
|
||||
"BSS removed: %pM\n",
|
||||
IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n",
|
||||
mgmt->bssid);
|
||||
list_del(&bss->node);
|
||||
kfree(bss->bss);
|
||||
|
@ -1223,18 +1249,24 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
|
|||
u8 source, cmd_id;
|
||||
u16 seq_num;
|
||||
u32 count;
|
||||
u8 resp;
|
||||
|
||||
wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
|
||||
cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
|
||||
|
||||
source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
|
||||
if (source >= IWM_SRC_NUM) {
|
||||
IWM_CRIT(iwm, "invalid source %d\n", source);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT));
|
||||
if (cmd_id == REPLY_RX_MPDU_CMD)
|
||||
trace_iwm_rx_packet(iwm, buf, buf_size);
|
||||
else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) &&
|
||||
(source == UMAC_HDI_IN_SOURCE_FW))
|
||||
trace_iwm_rx_ticket(iwm, buf, buf_size);
|
||||
else
|
||||
trace_iwm_rx_wifi_cmd(iwm, wifi_hdr);
|
||||
|
||||
count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
|
||||
count += sizeof(struct iwm_umac_wifi_in_hdr) -
|
||||
sizeof(struct iwm_dev_cmd_hdr);
|
||||
if (count > buf_size) {
|
||||
|
@ -1242,8 +1274,6 @@ static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS);
|
||||
|
||||
seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
|
||||
|
||||
IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
|
||||
|
@ -1316,8 +1346,9 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
|
|||
{
|
||||
u8 seq_num;
|
||||
struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
|
||||
struct iwm_nonwifi_cmd *cmd, *next;
|
||||
struct iwm_nonwifi_cmd *cmd;
|
||||
|
||||
trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size);
|
||||
seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
|
||||
|
||||
/*
|
||||
|
@ -1328,7 +1359,7 @@ static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
|
|||
* That means we only support synchronised non wifi command response
|
||||
* schemes.
|
||||
*/
|
||||
list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending)
|
||||
list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
|
||||
if (cmd->seq_num == seq_num) {
|
||||
cmd->resp_received = 1;
|
||||
cmd->buf.len = buf_size;
|
||||
|
@ -1647,6 +1678,7 @@ void iwm_rx_worker(struct work_struct *work)
|
|||
* We stop whenever a ticket is missing its packet, as we're
|
||||
* supposed to send the packets in order.
|
||||
*/
|
||||
spin_lock(&iwm->ticket_lock);
|
||||
list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
|
||||
struct iwm_rx_packet *packet =
|
||||
iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
|
||||
|
@ -1655,12 +1687,12 @@ void iwm_rx_worker(struct work_struct *work)
|
|||
IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
|
||||
"to be handled first\n",
|
||||
le16_to_cpu(ticket->ticket->id));
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
list_del(&ticket->node);
|
||||
list_del(&packet->node);
|
||||
iwm_rx_process_packet(iwm, packet, ticket);
|
||||
}
|
||||
spin_unlock(&iwm->ticket_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#include "iwm.h"
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
|
@ -0,0 +1,283 @@
|
|||
#if !defined(__IWM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define __IWM_TRACE_H__
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#if !defined(CONFIG_IWM_TRACING)
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#endif
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM iwm
|
||||
|
||||
#define IWM_ENTRY __array(char, ndev_name, 16)
|
||||
#define IWM_ASSIGN strlcpy(__entry->ndev_name, iwm_to_ndev(iwm)->name, 16)
|
||||
#define IWM_PR_FMT "%s"
|
||||
#define IWM_PR_ARG __entry->ndev_name
|
||||
|
||||
TRACE_EVENT(iwm_tx_nonwifi_cmd,
|
||||
TP_PROTO(struct iwm_priv *iwm, struct iwm_udma_out_nonwifi_hdr *hdr),
|
||||
|
||||
TP_ARGS(iwm, hdr),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, opcode)
|
||||
__field(u8, resp)
|
||||
__field(u8, eot)
|
||||
__field(u8, hw)
|
||||
__field(u16, seq)
|
||||
__field(u32, addr)
|
||||
__field(u32, op1)
|
||||
__field(u32, op2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
IWM_ASSIGN;
|
||||
__entry->opcode = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE);
|
||||
__entry->resp = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP);
|
||||
__entry->eot = GET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT);
|
||||
__entry->hw = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW);
|
||||
__entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM);
|
||||
__entry->addr = le32_to_cpu(hdr->addr);
|
||||
__entry->op1 = le32_to_cpu(hdr->op1_sz);
|
||||
__entry->op2 = le32_to_cpu(hdr->op2);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Tx TARGET CMD: opcode 0x%x, resp %d, eot %d, "
|
||||
"hw %d, seq 0x%x, addr 0x%x, op1 0x%x, op2 0x%x",
|
||||
IWM_PR_ARG, __entry->opcode, __entry->resp, __entry->eot,
|
||||
__entry->hw, __entry->seq, __entry->addr, __entry->op1,
|
||||
__entry->op2
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwm_tx_wifi_cmd,
|
||||
TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_out_hdr *hdr),
|
||||
|
||||
TP_ARGS(iwm, hdr),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, opcode)
|
||||
__field(u8, lmac)
|
||||
__field(u8, resp)
|
||||
__field(u8, eot)
|
||||
__field(u8, ra_tid)
|
||||
__field(u8, credit_group)
|
||||
__field(u8, color)
|
||||
__field(u16, seq)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
IWM_ASSIGN;
|
||||
__entry->opcode = hdr->sw_hdr.cmd.cmd;
|
||||
__entry->lmac = 0;
|
||||
__entry->seq = hdr->sw_hdr.cmd.seq_num;
|
||||
__entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ);
|
||||
__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
|
||||
__entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
|
||||
__entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
|
||||
__entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
|
||||
if (__entry->opcode == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH ||
|
||||
__entry->opcode == UMAC_CMD_OPCODE_WIFI_IF_WRAPPER) {
|
||||
__entry->lmac = 1;
|
||||
__entry->opcode = ((struct iwm_lmac_hdr *)(hdr + 1))->id;
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Tx %cMAC CMD: opcode 0x%x, resp %d, eot %d, "
|
||||
"seq 0x%x, sta_color 0x%x, ra_tid 0x%x, credit_group 0x%x",
|
||||
IWM_PR_ARG, __entry->lmac ? 'L' : 'U', __entry->opcode,
|
||||
__entry->resp, __entry->eot, __entry->seq, __entry->color,
|
||||
__entry->ra_tid, __entry->credit_group
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwm_tx_packets,
|
||||
TP_PROTO(struct iwm_priv *iwm, u8 *buf, int len),
|
||||
|
||||
TP_ARGS(iwm, buf, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, eot)
|
||||
__field(u8, ra_tid)
|
||||
__field(u8, credit_group)
|
||||
__field(u8, color)
|
||||
__field(u16, seq)
|
||||
__field(u8, npkt)
|
||||
__field(u32, bytes)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct iwm_umac_wifi_out_hdr *hdr =
|
||||
(struct iwm_umac_wifi_out_hdr *)buf;
|
||||
|
||||
IWM_ASSIGN;
|
||||
__entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
|
||||
__entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
|
||||
__entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
|
||||
__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
|
||||
__entry->seq = hdr->sw_hdr.cmd.seq_num;
|
||||
__entry->npkt = 1;
|
||||
__entry->bytes = len;
|
||||
|
||||
if (!__entry->eot) {
|
||||
int count;
|
||||
u8 *ptr = buf;
|
||||
|
||||
__entry->npkt = 0;
|
||||
while (ptr < buf + len) {
|
||||
count = GET_VAL32(hdr->sw_hdr.meta_data,
|
||||
UMAC_FW_CMD_BYTE_COUNT);
|
||||
ptr += ALIGN(sizeof(*hdr) + count, 16);
|
||||
hdr = (struct iwm_umac_wifi_out_hdr *)ptr;
|
||||
__entry->npkt++;
|
||||
}
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, "
|
||||
"ra_tid 0x%x, credit_group 0x%x, embeded_packets %d, %d bytes",
|
||||
IWM_PR_ARG, !__entry->eot ? "concatenated " : "",
|
||||
__entry->eot, __entry->seq, __entry->color, __entry->ra_tid,
|
||||
__entry->credit_group, __entry->npkt, __entry->bytes
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwm_rx_nonwifi_cmd,
|
||||
TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
|
||||
|
||||
TP_ARGS(iwm, buf, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, opcode)
|
||||
__field(u16, seq)
|
||||
__field(u32, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct iwm_udma_in_hdr *hdr = buf;
|
||||
|
||||
IWM_ASSIGN;
|
||||
__entry->opcode = GET_VAL32(hdr->cmd, UDMA_HDI_IN_NW_CMD_OPCODE);
|
||||
__entry->seq = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
|
||||
__entry->len = len;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Rx TARGET RESP: opcode 0x%x, seq 0x%x, len 0x%x",
|
||||
IWM_PR_ARG, __entry->opcode, __entry->seq, __entry->len
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwm_rx_wifi_cmd,
|
||||
TP_PROTO(struct iwm_priv *iwm, struct iwm_umac_wifi_in_hdr *hdr),
|
||||
|
||||
TP_ARGS(iwm, hdr),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, cmd)
|
||||
__field(u8, source)
|
||||
__field(u16, seq)
|
||||
__field(u32, count)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
IWM_ASSIGN;
|
||||
__entry->cmd = hdr->sw_hdr.cmd.cmd;
|
||||
__entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
|
||||
__entry->count = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
|
||||
__entry->seq = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Rx %s RESP: cmd 0x%x, seq 0x%x, count 0x%x",
|
||||
IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ? "LMAC" :
|
||||
__entry->source == UMAC_HDI_IN_SOURCE_FW ? "UMAC" : "UDMA",
|
||||
__entry->cmd, __entry->seq, __entry->count
|
||||
)
|
||||
);
|
||||
|
||||
#define iwm_ticket_action_symbol \
|
||||
{ IWM_RX_TICKET_DROP, "DROP" }, \
|
||||
{ IWM_RX_TICKET_RELEASE, "RELEASE" }, \
|
||||
{ IWM_RX_TICKET_SNIFFER, "SNIFFER" }, \
|
||||
{ IWM_RX_TICKET_ENQUEUE, "ENQUEUE" }
|
||||
|
||||
TRACE_EVENT(iwm_rx_ticket,
|
||||
TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
|
||||
|
||||
TP_ARGS(iwm, buf, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, action)
|
||||
__field(u8, reason)
|
||||
__field(u16, id)
|
||||
__field(u16, flags)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct iwm_rx_ticket *ticket =
|
||||
((struct iwm_umac_notif_rx_ticket *)buf)->tickets;
|
||||
|
||||
IWM_ASSIGN;
|
||||
__entry->id = le16_to_cpu(ticket->id);
|
||||
__entry->action = le16_to_cpu(ticket->action);
|
||||
__entry->flags = le16_to_cpu(ticket->flags);
|
||||
__entry->reason = (__entry->flags & IWM_RX_TICKET_DROP_REASON_MSK) >> IWM_RX_TICKET_DROP_REASON_POS;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Rx ticket: id 0x%x, action %s, %s 0x%x%s",
|
||||
IWM_PR_ARG, __entry->id,
|
||||
__print_symbolic(__entry->action, iwm_ticket_action_symbol),
|
||||
__entry->reason ? "reason" : "flags",
|
||||
__entry->reason ? __entry->reason : __entry->flags,
|
||||
__entry->flags & IWM_RX_TICKET_AMSDU_MSK ? ", AMSDU frame" : ""
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwm_rx_packet,
|
||||
TP_PROTO(struct iwm_priv *iwm, void *buf, int len),
|
||||
|
||||
TP_ARGS(iwm, buf, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
IWM_ENTRY
|
||||
__field(u8, source)
|
||||
__field(u16, id)
|
||||
__field(u32, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct iwm_umac_wifi_in_hdr *hdr = buf;
|
||||
|
||||
IWM_ASSIGN;
|
||||
__entry->source = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
|
||||
__entry->id = le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
|
||||
__entry->len = len - sizeof(*hdr);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
IWM_PR_FMT " Rx %s packet: id 0x%x, %d bytes",
|
||||
IWM_PR_ARG, __entry->source == UMAC_HDI_IN_SOURCE_FHRX ?
|
||||
"LMAC" : "UMAC", __entry->id, __entry->len
|
||||
)
|
||||
);
|
||||
#endif
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
#include <trace/define_trace.h>
|
|
@ -346,6 +346,7 @@ static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
|
|||
/* mark EOP for the last packet */
|
||||
iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1);
|
||||
|
||||
trace_iwm_tx_packets(iwm, txq->concat_buf, txq->concat_count);
|
||||
ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count);
|
||||
|
||||
txq->concat_count = 0;
|
||||
|
@ -450,7 +451,6 @@ void iwm_tx_worker(struct work_struct *work)
|
|||
int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
||||
{
|
||||
struct iwm_priv *iwm = ndev_to_iwm(netdev);
|
||||
struct net_device *ndev = iwm_to_ndev(iwm);
|
||||
struct wireless_dev *wdev = iwm_to_wdev(iwm);
|
||||
struct iwm_tx_info *tx_info;
|
||||
struct iwm_tx_queue *txq;
|
||||
|
@ -517,12 +517,12 @@ int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
|||
|
||||
queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
|
||||
|
||||
ndev->stats.tx_packets++;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
netdev->stats.tx_packets++;
|
||||
netdev->stats.tx_bytes += skb->len;
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
drop:
|
||||
ndev->stats.tx_dropped++;
|
||||
netdev->stats.tx_dropped++;
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
|
|
@ -362,7 +362,7 @@ struct iwm_udma_out_wifi_hdr {
|
|||
#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4
|
||||
#define IWM_RX_TICKET_AMSDU_MSK 0x8
|
||||
#define IWM_RX_TICKET_DROP_REASON_POS 4
|
||||
#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS)
|
||||
#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << IWM_RX_TICKET_DROP_REASON_POS)
|
||||
|
||||
#define IWM_RX_DROP_NO_DROP 0x0
|
||||
#define IWM_RX_DROP_BAD_CRC 0x1
|
||||
|
|
|
@ -38,10 +38,10 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
|
|||
struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* @brief This function computes the avgSNR .
|
||||
* @brief This function computes the avgSNR .
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @return avgSNR
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @return avgSNR
|
||||
*/
|
||||
static u8 lbs_getavgsnr(struct lbs_private *priv)
|
||||
{
|
||||
|
@ -56,10 +56,10 @@ static u8 lbs_getavgsnr(struct lbs_private *priv)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief This function computes the AvgNF
|
||||
* @brief This function computes the AvgNF
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @return AvgNF
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @return AvgNF
|
||||
*/
|
||||
static u8 lbs_getavgnf(struct lbs_private *priv)
|
||||
{
|
||||
|
@ -74,11 +74,11 @@ static u8 lbs_getavgnf(struct lbs_private *priv)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief This function save the raw SNR/NF to our internel buffer
|
||||
* @brief This function save the raw SNR/NF to our internel buffer
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param prxpd A pointer to rxpd structure of received packet
|
||||
* @return n/a
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param prxpd A pointer to rxpd structure of received packet
|
||||
* @return n/a
|
||||
*/
|
||||
static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
|
||||
{
|
||||
|
@ -93,11 +93,11 @@ static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief This function computes the RSSI in received packet.
|
||||
* @brief This function computes the RSSI in received packet.
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param prxpd A pointer to rxpd structure of received packet
|
||||
* @return n/a
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param prxpd A pointer to rxpd structure of received packet
|
||||
* @return n/a
|
||||
*/
|
||||
static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
|
||||
{
|
||||
|
@ -134,9 +134,9 @@ static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
|
|||
* @brief This function processes received packet and forwards it
|
||||
* to kernel/upper layer
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private
|
||||
* @param skb A pointer to skb which includes the received packet
|
||||
* @return 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)
|
||||
{
|
||||
|
@ -196,7 +196,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
|
|||
* before the snap_type.
|
||||
*/
|
||||
p_ethhdr = (struct ethhdr *)
|
||||
((u8 *) & p_rx_pkt->eth803_hdr
|
||||
((u8 *) &p_rx_pkt->eth803_hdr
|
||||
+ sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
|
||||
- sizeof(p_rx_pkt->eth803_hdr.dest_addr)
|
||||
- sizeof(p_rx_pkt->eth803_hdr.src_addr)
|
||||
|
@ -213,7 +213,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
|
|||
hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
|
||||
} else {
|
||||
lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
|
||||
(u8 *) & p_rx_pkt->rfc1042_hdr,
|
||||
(u8 *) &p_rx_pkt->rfc1042_hdr,
|
||||
sizeof(p_rx_pkt->rfc1042_hdr));
|
||||
|
||||
/* Chop off the rxpd */
|
||||
|
@ -254,8 +254,8 @@ EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
|
|||
* @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)
|
||||
*
|
||||
* @param rate Input rate
|
||||
* @return Output Rate (0 if invalid)
|
||||
* @param rate Input rate
|
||||
* @return Output Rate (0 if invalid)
|
||||
*/
|
||||
static u8 convert_mv_rate_to_radiotap(u8 rate)
|
||||
{
|
||||
|
@ -294,9 +294,9 @@ static u8 convert_mv_rate_to_radiotap(u8 rate)
|
|||
* @brief This function processes a received 802.11 packet and forwards it
|
||||
* to kernel/upper layer
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private
|
||||
* @param skb A pointer to skb which includes the received packet
|
||||
* @return 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)
|
||||
|
@ -313,7 +313,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
|
|||
p_rx_pkt = (struct rx80211packethdr *) skb->data;
|
||||
prxpd = &p_rx_pkt->rx_pd;
|
||||
|
||||
// lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
|
||||
/* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */
|
||||
|
||||
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
|
||||
lbs_deb_rx("rx err: frame received with bad length\n");
|
||||
|
|
|
@ -27,6 +27,17 @@ config HERMES
|
|||
configure your card and that /etc/pcmcia/wireless.opts works :
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
|
||||
|
||||
config HERMES_PRISM
|
||||
bool "Support Prism 2/2.5 chipset"
|
||||
depends on HERMES
|
||||
---help---
|
||||
|
||||
Say Y to enable support for Prism 2 and 2.5 chipsets. These
|
||||
chipsets are better handled by the hostap driver. This driver
|
||||
would not support WPA or firmware download for Prism chipset.
|
||||
|
||||
If you are not sure, say N.
|
||||
|
||||
config HERMES_CACHE_FW_ON_INIT
|
||||
bool "Cache Hermes firmware on driver initialisation"
|
||||
depends on HERMES
|
||||
|
@ -86,7 +97,7 @@ config NORTEL_HERMES
|
|||
|
||||
config PCI_HERMES
|
||||
tristate "Prism 2.5 PCI 802.11b adaptor support"
|
||||
depends on PCI && HERMES
|
||||
depends on PCI && HERMES && HERMES_PRISM
|
||||
help
|
||||
Enable support for PCI and mini-PCI 802.11b wireless NICs based on
|
||||
the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
|
||||
|
|
|
@ -262,6 +262,13 @@ int determine_fw_capabilities(struct orinoco_private *priv,
|
|||
if (fw_name)
|
||||
dev_info(dev, "Firmware determined as %s\n", fw_name);
|
||||
|
||||
#ifndef CONFIG_HERMES_PRISM
|
||||
if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
|
||||
dev_err(dev, "Support for Prism chipset is not enabled\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -374,87 +374,90 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
|
|||
"Pavel Roskin <proski@gnu.org>, et al)";
|
||||
|
||||
static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
|
||||
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
|
||||
PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
|
||||
PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
|
||||
PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
|
||||
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
|
||||
PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
|
||||
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
|
||||
PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
|
||||
PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
|
||||
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
|
||||
PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
|
||||
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
|
||||
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
|
||||
#ifdef CONFIG_HERMES_PRISM
|
||||
/* Only entries that certainly identify Prism chipset */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
|
||||
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
|
||||
PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
|
||||
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
|
||||
PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
|
||||
PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
|
||||
PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
|
||||
PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
|
||||
PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
|
||||
PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
|
||||
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
|
||||
PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
|
||||
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
|
||||
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
|
||||
PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
|
||||
PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
|
||||
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
|
||||
PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
|
||||
PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
|
||||
PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
|
||||
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
|
||||
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
|
||||
PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
|
||||
PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
|
||||
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
|
||||
PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
|
||||
PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
|
||||
PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
|
||||
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
|
||||
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
|
||||
PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
|
||||
PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
|
||||
PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
|
||||
PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
|
||||
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
|
||||
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
|
||||
PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
|
||||
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
|
||||
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
|
||||
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
|
||||
PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
|
||||
PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
|
||||
#endif
|
||||
PCMCIA_DEVICE_NULL,
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
|
||||
|
|
|
@ -545,6 +545,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
|||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_BEACON_FILTER |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
|
||||
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
|
|
|
@ -117,6 +117,7 @@ MODULE_PARM_DESC(workaround_interval,
|
|||
#define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d)
|
||||
#define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e)
|
||||
#define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f)
|
||||
#define OID_802_11_CAPABILITY cpu_to_le32(0x0d010122)
|
||||
#define OID_802_11_PMKID cpu_to_le32(0x0d010123)
|
||||
#define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203)
|
||||
#define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204)
|
||||
|
@ -358,6 +359,30 @@ struct ndis_80211_assoc_info {
|
|||
__le32 offset_resp_ies;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_auth_encr_pair {
|
||||
__le32 auth_mode;
|
||||
__le32 encr_mode;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_capability {
|
||||
__le32 length;
|
||||
__le32 version;
|
||||
__le32 num_pmkids;
|
||||
__le32 num_auth_encr_pair;
|
||||
struct ndis_80211_auth_encr_pair auth_encr_pair[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ndis_80211_bssid_info {
|
||||
u8 bssid[6];
|
||||
u8 pmkid[16];
|
||||
};
|
||||
|
||||
struct ndis_80211_pmkid {
|
||||
__le32 length;
|
||||
__le32 bssid_info_count;
|
||||
struct ndis_80211_bssid_info bssid_info[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* private data
|
||||
*/
|
||||
|
@ -476,13 +501,7 @@ struct rndis_wlan_private {
|
|||
/* encryption stuff */
|
||||
int encr_tx_key_index;
|
||||
struct rndis_wlan_encr_key encr_keys[4];
|
||||
enum nl80211_auth_type wpa_auth_type;
|
||||
int wpa_version;
|
||||
int wpa_keymgmt;
|
||||
int wpa_ie_len;
|
||||
u8 *wpa_ie;
|
||||
int wpa_cipher_pair;
|
||||
int wpa_cipher_group;
|
||||
|
||||
u8 command_buffer[COMMAND_BUFFER_SIZE];
|
||||
};
|
||||
|
@ -534,6 +553,14 @@ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *mac, struct station_info *sinfo);
|
||||
|
||||
static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa);
|
||||
|
||||
static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa);
|
||||
|
||||
static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev);
|
||||
|
||||
static struct cfg80211_ops rndis_config_ops = {
|
||||
.change_virtual_intf = rndis_change_virtual_intf,
|
||||
.scan = rndis_scan,
|
||||
|
@ -550,6 +577,9 @@ static struct cfg80211_ops rndis_config_ops = {
|
|||
.set_default_key = rndis_set_default_key,
|
||||
.get_station = rndis_get_station,
|
||||
.dump_station = rndis_dump_station,
|
||||
.set_pmksa = rndis_set_pmksa,
|
||||
.del_pmksa = rndis_del_pmksa,
|
||||
.flush_pmksa = rndis_flush_pmksa,
|
||||
};
|
||||
|
||||
static void *rndis_wiphy_privid = &rndis_wiphy_privid;
|
||||
|
@ -704,6 +734,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
|
|||
struct rndis_query_c *get_c;
|
||||
} u;
|
||||
int ret, buflen;
|
||||
int resplen, respoffs, copylen;
|
||||
|
||||
buflen = *len + sizeof(*u.get);
|
||||
if (buflen < CONTROL_BUFFER_SIZE)
|
||||
|
@ -733,11 +764,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
|
|||
le32_to_cpu(u.get_c->status));
|
||||
|
||||
if (ret == 0) {
|
||||
memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
|
||||
resplen = le32_to_cpu(u.get_c->len);
|
||||
respoffs = le32_to_cpu(u.get_c->offset) + 8;
|
||||
|
||||
ret = le32_to_cpu(u.get_c->len);
|
||||
if (ret > *len)
|
||||
*len = ret;
|
||||
if (respoffs > buflen) {
|
||||
/* Device returned data offset outside buffer, error. */
|
||||
netdev_dbg(dev->net, "%s(%s): received invalid "
|
||||
"data offset: %d > %d\n", __func__,
|
||||
oid_to_string(oid), respoffs, buflen);
|
||||
|
||||
ret = -EINVAL;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
if ((resplen + respoffs) > buflen) {
|
||||
/* Device would have returned more data if buffer would
|
||||
* have been big enough. Copy just the bits that we got.
|
||||
*/
|
||||
copylen = buflen - respoffs;
|
||||
} else {
|
||||
copylen = resplen;
|
||||
}
|
||||
|
||||
if (copylen > *len)
|
||||
copylen = *len;
|
||||
|
||||
memcpy(data, u.buf + respoffs, copylen);
|
||||
|
||||
*len = resplen;
|
||||
|
||||
ret = rndis_error_status(u.get_c->status);
|
||||
if (ret < 0)
|
||||
|
@ -746,6 +800,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
|
|||
le32_to_cpu(u.get_c->status), ret);
|
||||
}
|
||||
|
||||
exit_unlock:
|
||||
mutex_unlock(&priv->command_lock);
|
||||
|
||||
if (u.buf != priv->command_buffer)
|
||||
|
@ -1091,8 +1146,6 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
|
|||
}
|
||||
|
||||
priv->wpa_version = wpa_version;
|
||||
priv->wpa_auth_type = auth_type;
|
||||
priv->wpa_keymgmt = keymgmt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1117,7 +1170,6 @@ static int set_priv_filter(struct usbnet *usbdev)
|
|||
|
||||
static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
__le32 tmp;
|
||||
int encr_mode, ret;
|
||||
|
||||
|
@ -1146,8 +1198,6 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
|
|||
return ret;
|
||||
}
|
||||
|
||||
priv->wpa_cipher_pair = pairwise;
|
||||
priv->wpa_cipher_group = groupwise;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1568,6 +1618,194 @@ set_filter:
|
|||
le32_to_cpu(filter), ret);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void debug_print_pmkids(struct usbnet *usbdev,
|
||||
struct ndis_80211_pmkid *pmkids,
|
||||
const char *func_str)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
int i, len, count, max_pmkids, entry_len;
|
||||
|
||||
max_pmkids = priv->wdev.wiphy->max_num_pmkids;
|
||||
len = le32_to_cpu(pmkids->length);
|
||||
count = le32_to_cpu(pmkids->bssid_info_count);
|
||||
|
||||
entry_len = (count > 0) ? (len - sizeof(*pmkids)) / count : -1;
|
||||
|
||||
netdev_dbg(usbdev->net, "%s(): %d PMKIDs (data len: %d, entry len: "
|
||||
"%d)\n", func_str, count, len, entry_len);
|
||||
|
||||
if (count > max_pmkids)
|
||||
count = max_pmkids;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
u32 *tmp = (u32 *)pmkids->bssid_info[i].pmkid;
|
||||
|
||||
netdev_dbg(usbdev->net, "%s(): bssid: %pM, "
|
||||
"pmkid: %08X:%08X:%08X:%08X\n",
|
||||
func_str, pmkids->bssid_info[i].bssid,
|
||||
cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]),
|
||||
cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3]));
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void debug_print_pmkids(struct usbnet *usbdev,
|
||||
struct ndis_80211_pmkid *pmkids,
|
||||
const char *func_str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct ndis_80211_pmkid *get_device_pmkids(struct usbnet *usbdev)
|
||||
{
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
struct ndis_80211_pmkid *pmkids;
|
||||
int len, ret, max_pmkids;
|
||||
|
||||
max_pmkids = priv->wdev.wiphy->max_num_pmkids;
|
||||
len = sizeof(*pmkids) + max_pmkids * sizeof(pmkids->bssid_info[0]);
|
||||
|
||||
pmkids = kzalloc(len, GFP_KERNEL);
|
||||
if (!pmkids)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pmkids->length = cpu_to_le32(len);
|
||||
pmkids->bssid_info_count = cpu_to_le32(max_pmkids);
|
||||
|
||||
ret = rndis_query_oid(usbdev, OID_802_11_PMKID, pmkids, &len);
|
||||
if (ret < 0) {
|
||||
netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d)"
|
||||
" -> %d\n", __func__, len, max_pmkids, ret);
|
||||
|
||||
kfree(pmkids);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (le32_to_cpu(pmkids->bssid_info_count) > max_pmkids)
|
||||
pmkids->bssid_info_count = cpu_to_le32(max_pmkids);
|
||||
|
||||
debug_print_pmkids(usbdev, pmkids, __func__);
|
||||
|
||||
return pmkids;
|
||||
}
|
||||
|
||||
static int set_device_pmkids(struct usbnet *usbdev,
|
||||
struct ndis_80211_pmkid *pmkids)
|
||||
{
|
||||
int ret, len, num_pmkids;
|
||||
|
||||
num_pmkids = le32_to_cpu(pmkids->bssid_info_count);
|
||||
len = sizeof(*pmkids) + num_pmkids * sizeof(pmkids->bssid_info[0]);
|
||||
pmkids->length = cpu_to_le32(len);
|
||||
|
||||
debug_print_pmkids(usbdev, pmkids, __func__);
|
||||
|
||||
ret = rndis_set_oid(usbdev, OID_802_11_PMKID, pmkids,
|
||||
le32_to_cpu(pmkids->length));
|
||||
if (ret < 0) {
|
||||
netdev_dbg(usbdev->net, "%s(): OID_802_11_PMKID(%d, %d) -> %d"
|
||||
"\n", __func__, len, num_pmkids, ret);
|
||||
}
|
||||
|
||||
kfree(pmkids);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev,
|
||||
struct ndis_80211_pmkid *pmkids,
|
||||
struct cfg80211_pmksa *pmksa,
|
||||
int max_pmkids)
|
||||
{
|
||||
int i, len, count, newlen, err;
|
||||
|
||||
len = le32_to_cpu(pmkids->length);
|
||||
count = le32_to_cpu(pmkids->bssid_info_count);
|
||||
|
||||
if (count > max_pmkids)
|
||||
count = max_pmkids;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (!compare_ether_addr(pmkids->bssid_info[i].bssid,
|
||||
pmksa->bssid))
|
||||
break;
|
||||
|
||||
/* pmkid not found */
|
||||
if (i == count) {
|
||||
netdev_dbg(usbdev->net, "%s(): bssid not found (%pM)\n",
|
||||
__func__, pmksa->bssid);
|
||||
err = -ENOENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (; i + 1 < count; i++)
|
||||
pmkids->bssid_info[i] = pmkids->bssid_info[i + 1];
|
||||
|
||||
count--;
|
||||
newlen = sizeof(*pmkids) + count * sizeof(pmkids->bssid_info[0]);
|
||||
|
||||
pmkids->length = cpu_to_le32(newlen);
|
||||
pmkids->bssid_info_count = cpu_to_le32(count);
|
||||
|
||||
return pmkids;
|
||||
error:
|
||||
kfree(pmkids);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev,
|
||||
struct ndis_80211_pmkid *pmkids,
|
||||
struct cfg80211_pmksa *pmksa,
|
||||
int max_pmkids)
|
||||
{
|
||||
int i, err, len, count, newlen;
|
||||
|
||||
len = le32_to_cpu(pmkids->length);
|
||||
count = le32_to_cpu(pmkids->bssid_info_count);
|
||||
|
||||
if (count > max_pmkids)
|
||||
count = max_pmkids;
|
||||
|
||||
/* update with new pmkid */
|
||||
for (i = 0; i < count; i++) {
|
||||
if (compare_ether_addr(pmkids->bssid_info[i].bssid,
|
||||
pmksa->bssid))
|
||||
continue;
|
||||
|
||||
memcpy(pmkids->bssid_info[i].pmkid, pmksa->pmkid,
|
||||
WLAN_PMKID_LEN);
|
||||
|
||||
return pmkids;
|
||||
}
|
||||
|
||||
/* out of space, return error */
|
||||
if (i == max_pmkids) {
|
||||
netdev_dbg(usbdev->net, "%s(): out of space\n", __func__);
|
||||
err = -ENOSPC;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* add new pmkid */
|
||||
newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]);
|
||||
|
||||
pmkids = krealloc(pmkids, newlen, GFP_KERNEL);
|
||||
if (!pmkids) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pmkids->length = cpu_to_le32(newlen);
|
||||
pmkids->bssid_info_count = cpu_to_le32(count + 1);
|
||||
|
||||
memcpy(pmkids->bssid_info[count].bssid, pmksa->bssid, ETH_ALEN);
|
||||
memcpy(pmkids->bssid_info[count].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
|
||||
|
||||
return pmkids;
|
||||
error:
|
||||
kfree(pmkids);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* cfg80211 ops
|
||||
*/
|
||||
|
@ -2178,6 +2416,78 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa)
|
||||
{
|
||||
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
struct ndis_80211_pmkid *pmkids;
|
||||
u32 *tmp = (u32 *)pmksa->pmkid;
|
||||
|
||||
netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__,
|
||||
pmksa->bssid,
|
||||
cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]),
|
||||
cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3]));
|
||||
|
||||
pmkids = get_device_pmkids(usbdev);
|
||||
if (IS_ERR(pmkids)) {
|
||||
/* couldn't read PMKID cache from device */
|
||||
return PTR_ERR(pmkids);
|
||||
}
|
||||
|
||||
pmkids = update_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids);
|
||||
if (IS_ERR(pmkids)) {
|
||||
/* not found, list full, etc */
|
||||
return PTR_ERR(pmkids);
|
||||
}
|
||||
|
||||
return set_device_pmkids(usbdev, pmkids);
|
||||
}
|
||||
|
||||
static int rndis_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_pmksa *pmksa)
|
||||
{
|
||||
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
struct ndis_80211_pmkid *pmkids;
|
||||
u32 *tmp = (u32 *)pmksa->pmkid;
|
||||
|
||||
netdev_dbg(usbdev->net, "%s(%pM, %08X:%08X:%08X:%08X)\n", __func__,
|
||||
pmksa->bssid,
|
||||
cpu_to_be32(tmp[0]), cpu_to_be32(tmp[1]),
|
||||
cpu_to_be32(tmp[2]), cpu_to_be32(tmp[3]));
|
||||
|
||||
pmkids = get_device_pmkids(usbdev);
|
||||
if (IS_ERR(pmkids)) {
|
||||
/* Couldn't read PMKID cache from device */
|
||||
return PTR_ERR(pmkids);
|
||||
}
|
||||
|
||||
pmkids = remove_pmkid(usbdev, pmkids, pmksa, wiphy->max_num_pmkids);
|
||||
if (IS_ERR(pmkids)) {
|
||||
/* not found, etc */
|
||||
return PTR_ERR(pmkids);
|
||||
}
|
||||
|
||||
return set_device_pmkids(usbdev, pmkids);
|
||||
}
|
||||
|
||||
static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
|
||||
{
|
||||
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
struct ndis_80211_pmkid pmkid;
|
||||
|
||||
netdev_dbg(usbdev->net, "%s()\n", __func__);
|
||||
|
||||
memset(&pmkid, 0, sizeof(pmkid));
|
||||
|
||||
pmkid.length = cpu_to_le32(sizeof(pmkid));
|
||||
pmkid.bssid_info_count = cpu_to_le32(0);
|
||||
|
||||
return rndis_set_oid(usbdev, OID_802_11_PMKID, &pmkid, sizeof(pmkid));
|
||||
}
|
||||
|
||||
/*
|
||||
* workers, indication handlers, device poller
|
||||
*/
|
||||
|
@ -2522,12 +2832,14 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
|
|||
}
|
||||
}
|
||||
|
||||
static int rndis_wlan_get_caps(struct usbnet *usbdev)
|
||||
static int rndis_wlan_get_caps(struct usbnet *usbdev, struct wiphy *wiphy)
|
||||
{
|
||||
struct {
|
||||
__le32 num_items;
|
||||
__le32 items[8];
|
||||
} networks_supported;
|
||||
struct ndis_80211_capability *caps;
|
||||
u8 caps_buf[sizeof(*caps) + sizeof(caps->auth_encr_pair) * 16];
|
||||
int len, retval, i, n;
|
||||
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
||||
|
||||
|
@ -2555,6 +2867,21 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* get device 802.11 capabilities, number of PMKIDs */
|
||||
caps = (struct ndis_80211_capability *)caps_buf;
|
||||
len = sizeof(caps_buf);
|
||||
retval = rndis_query_oid(usbdev, OID_802_11_CAPABILITY, caps, &len);
|
||||
if (retval >= 0) {
|
||||
netdev_dbg(usbdev->net, "OID_802_11_CAPABILITY -> len %d, "
|
||||
"ver %d, pmkids %d, auth-encr-pairs %d\n",
|
||||
le32_to_cpu(caps->length),
|
||||
le32_to_cpu(caps->version),
|
||||
le32_to_cpu(caps->num_pmkids),
|
||||
le32_to_cpu(caps->num_auth_encr_pair));
|
||||
wiphy->max_num_pmkids = le32_to_cpu(caps->num_pmkids);
|
||||
} else
|
||||
wiphy->max_num_pmkids = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2802,7 +3129,7 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
|||
wiphy->max_scan_ssids = 1;
|
||||
|
||||
/* TODO: fill-out band/encr information based on priv->caps */
|
||||
rndis_wlan_get_caps(usbdev);
|
||||
rndis_wlan_get_caps(usbdev, wiphy);
|
||||
|
||||
memcpy(priv->channels, rndis_channels, sizeof(rndis_channels));
|
||||
memcpy(priv->rates, rndis_rates, sizeof(rndis_rates));
|
||||
|
@ -2862,9 +3189,6 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
|
|||
flush_workqueue(priv->workqueue);
|
||||
destroy_workqueue(priv->workqueue);
|
||||
|
||||
if (priv && priv->wpa_ie_len)
|
||||
kfree(priv->wpa_ie);
|
||||
|
||||
rndis_unbind(usbdev, intf);
|
||||
|
||||
wiphy_unregister(priv->wdev.wiphy);
|
||||
|
|
|
@ -907,14 +907,12 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
|
|||
{
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
struct queue_entry *entry_done;
|
||||
struct queue_entry_priv_pci *entry_priv;
|
||||
__le32 *txwi;
|
||||
struct txdone_entry_desc txdesc;
|
||||
u32 word;
|
||||
u32 reg;
|
||||
u32 old_reg;
|
||||
unsigned int type;
|
||||
unsigned int index;
|
||||
int wcid, ack, pid, tx_wcid, tx_ack, tx_pid;
|
||||
u16 mcs, real_mcs;
|
||||
|
||||
/*
|
||||
|
@ -936,71 +934,76 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
|
|||
break;
|
||||
old_reg = reg;
|
||||
|
||||
wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
|
||||
ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
|
||||
pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
|
||||
|
||||
/*
|
||||
* Skip this entry when it contains an invalid
|
||||
* queue identication number.
|
||||
*/
|
||||
type = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1;
|
||||
if (type >= QID_RX)
|
||||
if (pid <= 0 || pid > QID_RX)
|
||||
continue;
|
||||
|
||||
queue = rt2x00queue_get_queue(rt2x00dev, type);
|
||||
queue = rt2x00queue_get_queue(rt2x00dev, pid - 1);
|
||||
if (unlikely(!queue))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Skip this entry when it contains an invalid
|
||||
* index number.
|
||||
* Inside each queue, we process each entry in a chronological
|
||||
* order. We first check that the queue is not empty.
|
||||
*/
|
||||
index = rt2x00_get_field32(reg, TX_STA_FIFO_WCID) - 1;
|
||||
if (unlikely(index >= queue->limit))
|
||||
if (rt2x00queue_empty(queue))
|
||||
continue;
|
||||
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
|
||||
entry = &queue->entries[index];
|
||||
entry_priv = entry->priv_data;
|
||||
rt2x00_desc_read((__le32 *)entry->skb->data, 0, &word);
|
||||
/* Check if we got a match by looking at WCID/ACK/PID
|
||||
* fields */
|
||||
txwi = (__le32 *)(entry->skb->data -
|
||||
rt2x00dev->ops->extra_tx_headroom);
|
||||
|
||||
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
while (entry != entry_done) {
|
||||
/*
|
||||
* Catch up.
|
||||
* Just report any entries we missed as failed.
|
||||
*/
|
||||
WARNING(rt2x00dev,
|
||||
"TX status report missed for entry %d\n",
|
||||
entry_done->entry_idx);
|
||||
rt2x00_desc_read(txwi, 1, &word);
|
||||
tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
|
||||
tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
|
||||
tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
|
||||
|
||||
txdesc.flags = 0;
|
||||
__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
|
||||
txdesc.retry = 0;
|
||||
|
||||
rt2x00lib_txdone(entry_done, &txdesc);
|
||||
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
|
||||
}
|
||||
if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid))
|
||||
WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n");
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
*/
|
||||
txdesc.flags = 0;
|
||||
if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS))
|
||||
__set_bit(TXDONE_SUCCESS, &txdesc.flags);
|
||||
else
|
||||
__set_bit(TXDONE_FAILURE, &txdesc.flags);
|
||||
rt2x00_desc_read(txwi, 0, &word);
|
||||
mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
|
||||
real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS);
|
||||
|
||||
/*
|
||||
* Ralink has a retry mechanism using a global fallback
|
||||
* table. We setup this fallback table to try immediate
|
||||
* lower rate for all rates. In the TX_STA_FIFO,
|
||||
* the MCS field contains the MCS used for the successfull
|
||||
* transmission. If the first transmission succeed,
|
||||
* we have mcs == tx_mcs. On the second transmission,
|
||||
* we have mcs = tx_mcs - 1. So the number of
|
||||
* retry is (tx_mcs - mcs).
|
||||
* table. We setup this fallback table to try the immediate
|
||||
* lower rate for all rates. In the TX_STA_FIFO, the MCS field
|
||||
* always contains the MCS used for the last transmission, be
|
||||
* it successful or not.
|
||||
*/
|
||||
mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
|
||||
real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS);
|
||||
if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) {
|
||||
/*
|
||||
* Transmission succeeded. The number of retries is
|
||||
* mcs - real_mcs
|
||||
*/
|
||||
__set_bit(TXDONE_SUCCESS, &txdesc.flags);
|
||||
txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
|
||||
} else {
|
||||
/*
|
||||
* Transmission failed. The number of retries is
|
||||
* always 7 in this case (for a total number of 8
|
||||
* frames sent).
|
||||
*/
|
||||
__set_bit(TXDONE_FAILURE, &txdesc.flags);
|
||||
txdesc.retry = 7;
|
||||
}
|
||||
|
||||
__set_bit(TXDONE_FALLBACK, &txdesc.flags);
|
||||
txdesc.retry = mcs - min(mcs, real_mcs);
|
||||
|
||||
|
||||
rt2x00lib_txdone(entry, &txdesc);
|
||||
}
|
||||
|
@ -1184,6 +1187,7 @@ static const struct rt2x00_ops rt2800pci_ops = {
|
|||
/*
|
||||
* RT2800pci module information.
|
||||
*/
|
||||
#ifdef CONFIG_RT2800PCI_PCI
|
||||
static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
|
||||
{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
|
@ -1211,6 +1215,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
|
|||
#endif
|
||||
{ 0, }
|
||||
};
|
||||
#endif /* CONFIG_RT2800PCI_PCI */
|
||||
|
||||
MODULE_AUTHOR(DRV_PROJECT);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
|
|
@ -51,3 +51,27 @@ config WL1271
|
|||
|
||||
If you choose to build a module, it'll be called wl1271. Say N if
|
||||
unsure.
|
||||
|
||||
config WL1271_SPI
|
||||
tristate "TI wl1271 SPI support"
|
||||
depends on WL1271 && SPI_MASTER
|
||||
---help---
|
||||
This module adds support for the SPI interface of adapters using
|
||||
TI wl1271 chipset. Select this if your platform is using
|
||||
the SPI bus.
|
||||
|
||||
If you choose to build a module, it'll be called wl1251_spi.
|
||||
Say N if unsure.
|
||||
|
||||
config WL1271_SDIO
|
||||
tristate "TI wl1271 SDIO support"
|
||||
depends on WL1271 && MMC && ARM
|
||||
---help---
|
||||
This module adds support for the SDIO interface of adapters using
|
||||
TI wl1271 chipset. Select this if your platform is using
|
||||
the SDIO bus.
|
||||
|
||||
If you choose to build a module, it'll be called
|
||||
wl1271_sdio. Say N if unsure.
|
||||
|
||||
|
||||
|
|
|
@ -7,10 +7,12 @@ obj-$(CONFIG_WL1251) += wl1251.o
|
|||
obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
|
||||
obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
|
||||
|
||||
wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
|
||||
wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \
|
||||
wl1271_event.o wl1271_tx.o wl1271_rx.o \
|
||||
wl1271_ps.o wl1271_acx.o wl1271_boot.o \
|
||||
wl1271_init.o wl1271_debugfs.o wl1271_io.o
|
||||
wl1271_init.o wl1271_debugfs.o
|
||||
|
||||
wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
|
||||
obj-$(CONFIG_WL1271) += wl1271.o
|
||||
obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o
|
||||
obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o
|
||||
|
|
|
@ -256,6 +256,8 @@ struct wl1251_debugfs {
|
|||
struct wl1251_if_operations {
|
||||
void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
|
||||
void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
|
||||
void (*read_elp)(struct wl1251 *wl, int addr, u32 *val);
|
||||
void (*write_elp)(struct wl1251 *wl, int addr, u32 val);
|
||||
void (*reset)(struct wl1251 *wl);
|
||||
void (*enable_irq)(struct wl1251 *wl);
|
||||
void (*disable_irq)(struct wl1251 *wl);
|
||||
|
|
|
@ -496,7 +496,8 @@ int wl1251_boot(struct wl1251 *wl)
|
|||
/* 2. start processing NVS file */
|
||||
if (wl->use_eeprom) {
|
||||
wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
|
||||
msleep(4000);
|
||||
/* Wait for EEPROM NVS burst read to complete */
|
||||
msleep(40);
|
||||
wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
|
||||
} else {
|
||||
ret = wl1251_boot_upload_nvs(wl);
|
||||
|
|
|
@ -48,6 +48,26 @@ static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
|
|||
wl->if_ops->write(wl, addr, &val, sizeof(u32));
|
||||
}
|
||||
|
||||
static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr)
|
||||
{
|
||||
u32 response;
|
||||
|
||||
if (wl->if_ops->read_elp)
|
||||
wl->if_ops->read_elp(wl, addr, &response);
|
||||
else
|
||||
wl->if_ops->read(wl, addr, &response, sizeof(u32));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val)
|
||||
{
|
||||
if (wl->if_ops->write_elp)
|
||||
wl->if_ops->write_elp(wl, addr, val);
|
||||
else
|
||||
wl->if_ops->write(wl, addr, &val, sizeof(u32));
|
||||
}
|
||||
|
||||
/* Memory target IO, address is translated to partition 0 */
|
||||
void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
|
||||
void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
|
||||
|
|
|
@ -146,8 +146,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl)
|
|||
u32 elp_reg;
|
||||
|
||||
elp_reg = ELPCTRL_WAKE_UP;
|
||||
wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
|
||||
elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
|
||||
wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
|
||||
elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
|
||||
|
||||
if (!(elp_reg & ELPCTRL_WLAN_READY))
|
||||
wl1251_warning("WLAN not ready");
|
||||
|
|
|
@ -45,7 +45,7 @@ void wl1251_elp_work(struct work_struct *work)
|
|||
goto out;
|
||||
|
||||
wl1251_debug(DEBUG_PSM, "chip to elp");
|
||||
wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
|
||||
wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
|
||||
wl->elp = true;
|
||||
|
||||
out:
|
||||
|
@ -79,9 +79,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
|
|||
start = jiffies;
|
||||
timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
|
||||
|
||||
wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
|
||||
wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
|
||||
|
||||
elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
|
||||
elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
|
||||
|
||||
/*
|
||||
* FIXME: we should wait for irq from chip but, as a temporary
|
||||
|
@ -93,7 +93,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(1);
|
||||
elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
|
||||
elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
|
||||
}
|
||||
|
||||
wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
|
||||
|
|
|
@ -20,20 +20,11 @@
|
|||
* Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/crc7.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "wl1251.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1251_reg.h"
|
||||
#include "wl1251_ps.h"
|
||||
#include "wl1251_io.h"
|
||||
#include "wl1251_tx.h"
|
||||
#include "wl1251_debugfs.h"
|
||||
|
||||
#ifndef SDIO_VENDOR_ID_TI
|
||||
#define SDIO_VENDOR_ID_TI 0x104c
|
||||
|
@ -65,7 +56,8 @@ static const struct sdio_device_id wl1251_devices[] = {
|
|||
MODULE_DEVICE_TABLE(sdio, wl1251_devices);
|
||||
|
||||
|
||||
void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len)
|
||||
static void wl1251_sdio_read(struct wl1251 *wl, int addr,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
struct sdio_func *func = wl_to_func(wl);
|
||||
|
@ -77,7 +69,8 @@ void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len)
|
|||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len)
|
||||
static void wl1251_sdio_write(struct wl1251 *wl, int addr,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
struct sdio_func *func = wl_to_func(wl);
|
||||
|
@ -89,7 +82,33 @@ void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len)
|
|||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
void wl1251_sdio_reset(struct wl1251 *wl)
|
||||
static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sdio_func *func = wl_to_func(wl);
|
||||
|
||||
sdio_claim_host(func);
|
||||
*val = sdio_readb(func, addr, &ret);
|
||||
sdio_release_host(func);
|
||||
|
||||
if (ret)
|
||||
wl1251_error("sdio_readb failed (%d)", ret);
|
||||
}
|
||||
|
||||
static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sdio_func *func = wl_to_func(wl);
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_writeb(func, val, addr, &ret);
|
||||
sdio_release_host(func);
|
||||
|
||||
if (ret)
|
||||
wl1251_error("sdio_writeb failed (%d)", ret);
|
||||
}
|
||||
|
||||
static void wl1251_sdio_reset(struct wl1251 *wl)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -111,19 +130,22 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl)
|
|||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
void wl1251_sdio_set_power(bool enable)
|
||||
static void wl1251_sdio_set_power(bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
struct wl1251_if_operations wl1251_sdio_ops = {
|
||||
static const struct wl1251_if_operations wl1251_sdio_ops = {
|
||||
.read = wl1251_sdio_read,
|
||||
.write = wl1251_sdio_write,
|
||||
.write_elp = wl1251_sdio_write_elp,
|
||||
.read_elp = wl1251_sdio_read_elp,
|
||||
.reset = wl1251_sdio_reset,
|
||||
.enable_irq = wl1251_sdio_enable_irq,
|
||||
.disable_irq = wl1251_sdio_disable_irq,
|
||||
};
|
||||
|
||||
int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
||||
static int wl1251_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct wl1251 *wl;
|
||||
|
|
|
@ -110,6 +110,9 @@ enum {
|
|||
#define WL1271_FW_NAME "wl1271-fw.bin"
|
||||
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
||||
|
||||
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
|
||||
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
|
||||
|
||||
/* NVS data structure */
|
||||
#define WL1271_NVS_SECTION_SIZE 468
|
||||
|
||||
|
@ -334,11 +337,25 @@ struct wl1271_scan {
|
|||
u8 probe_requests;
|
||||
};
|
||||
|
||||
struct wl1271_if_operations {
|
||||
void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
void (*reset)(struct wl1271 *wl);
|
||||
void (*init)(struct wl1271 *wl);
|
||||
struct device* (*dev)(struct wl1271 *wl);
|
||||
void (*enable_irq)(struct wl1271 *wl);
|
||||
void (*disable_irq)(struct wl1271 *wl);
|
||||
};
|
||||
|
||||
struct wl1271 {
|
||||
struct ieee80211_hw *hw;
|
||||
bool mac80211_registered;
|
||||
|
||||
struct spi_device *spi;
|
||||
void *if_priv;
|
||||
|
||||
struct wl1271_if_operations *if_ops;
|
||||
|
||||
void (*set_power)(bool enable);
|
||||
int irq;
|
||||
|
@ -357,6 +374,8 @@ struct wl1271 {
|
|||
#define WL1271_FLAG_IN_ELP (6)
|
||||
#define WL1271_FLAG_PSM (7)
|
||||
#define WL1271_FLAG_PSM_REQUESTED (8)
|
||||
#define WL1271_FLAG_IRQ_PENDING (9)
|
||||
#define WL1271_FLAG_IRQ_RUNNING (10)
|
||||
unsigned long flags;
|
||||
|
||||
struct wl1271_partition_set part;
|
||||
|
@ -382,13 +401,13 @@ struct wl1271 {
|
|||
/* Accounting for allocated / available TX blocks on HW */
|
||||
u32 tx_blocks_freed[NUM_TX_QUEUES];
|
||||
u32 tx_blocks_available;
|
||||
u8 tx_results_count;
|
||||
u32 tx_results_count;
|
||||
|
||||
/* Transmitted TX packets counter for chipset interface */
|
||||
int tx_packets_count;
|
||||
u32 tx_packets_count;
|
||||
|
||||
/* Time-offset between host and chipset clocks */
|
||||
int time_offset;
|
||||
s64 time_offset;
|
||||
|
||||
/* Session counter for the chipset */
|
||||
int session_counter;
|
||||
|
@ -403,8 +422,7 @@ struct wl1271 {
|
|||
|
||||
/* Security sequence number counters */
|
||||
u8 tx_security_last_seq;
|
||||
u16 tx_security_seq_16;
|
||||
u32 tx_security_seq_32;
|
||||
s64 tx_security_seq;
|
||||
|
||||
/* FW Rx counter */
|
||||
u32 rx_counter;
|
||||
|
@ -477,7 +495,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
|
|||
|
||||
#define WL1271_DEFAULT_POWER_LEVEL 0
|
||||
|
||||
#define WL1271_TX_QUEUE_MAX_LENGTH 20
|
||||
#define WL1271_TX_QUEUE_LOW_WATERMARK 10
|
||||
#define WL1271_TX_QUEUE_HIGH_WATERMARK 25
|
||||
|
||||
/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
|
||||
on in case is has been shut down shortly before */
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "wl1271.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_ps.h"
|
||||
|
||||
int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
|
||||
|
@ -136,12 +135,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This is a workaround needed while we don't the correct
|
||||
* calibration, to avoid distortions
|
||||
*/
|
||||
/* acx->current_tx_power = power * 10; */
|
||||
acx->current_tx_power = 120;
|
||||
acx->current_tx_power = power * 10;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "wl1271_acx.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_boot.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_event.h"
|
||||
|
||||
|
@ -299,7 +298,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
|||
|
||||
static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
enable_irq(wl->irq);
|
||||
wl1271_enable_interrupts(wl);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
|
||||
wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_acx.h"
|
||||
#include "wl12xx_80211.h"
|
||||
|
@ -248,7 +247,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_join(struct wl1271 *wl)
|
||||
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
|
||||
{
|
||||
static bool do_cal = true;
|
||||
struct wl1271_cmd_join *join;
|
||||
|
@ -279,7 +278,7 @@ int wl1271_cmd_join(struct wl1271 *wl)
|
|||
|
||||
join->rx_config_options = cpu_to_le32(wl->rx_config);
|
||||
join->rx_filter_options = cpu_to_le32(wl->rx_filter);
|
||||
join->bss_type = wl->bss_type;
|
||||
join->bss_type = bss_type;
|
||||
|
||||
/*
|
||||
* FIXME: disable temporarily all filters because after commit
|
||||
|
@ -319,8 +318,7 @@ int wl1271_cmd_join(struct wl1271 *wl)
|
|||
|
||||
/* reset TX security counters */
|
||||
wl->tx_security_last_seq = 0;
|
||||
wl->tx_security_seq_16 = 0;
|
||||
wl->tx_security_seq_32 = 0;
|
||||
wl->tx_security_seq = 0;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -33,7 +33,7 @@ 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 wl1271_cmd_radio_parms(struct wl1271 *wl);
|
||||
int wl1271_cmd_join(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);
|
||||
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_event.h"
|
||||
#include "wl1271_ps.h"
|
||||
|
|
|
@ -28,30 +28,29 @@
|
|||
|
||||
#include "wl1271.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
static int wl1271_translate_addr(struct wl1271 *wl, int addr)
|
||||
#define OCP_CMD_LOOP 32
|
||||
|
||||
#define OCP_CMD_WRITE 0x1
|
||||
#define OCP_CMD_READ 0x2
|
||||
|
||||
#define OCP_READY_MASK BIT(18)
|
||||
#define OCP_STATUS_MASK (BIT(16) | BIT(17))
|
||||
|
||||
#define OCP_STATUS_NO_RESP 0x00000
|
||||
#define OCP_STATUS_OK 0x10000
|
||||
#define OCP_STATUS_REQ_FAILED 0x20000
|
||||
#define OCP_STATUS_RESP_ERROR 0x30000
|
||||
|
||||
void wl1271_disable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
/*
|
||||
* To translate, first check to which window of addresses the
|
||||
* particular address belongs. Then subtract the starting address
|
||||
* of that window from the address. Then, add offset of the
|
||||
* translated region.
|
||||
*
|
||||
* The translated regions occur next to each other in physical device
|
||||
* memory, so just add the sizes of the preceeding address regions to
|
||||
* get the offset to the new region.
|
||||
*
|
||||
* Currently, only the two first regions are addressed, and the
|
||||
* assumption is that all addresses will fall into either of those
|
||||
* two.
|
||||
*/
|
||||
if ((addr >= wl->part.reg.start) &&
|
||||
(addr < wl->part.reg.start + wl->part.reg.size))
|
||||
return addr - wl->part.reg.start + wl->part.mem.size;
|
||||
else
|
||||
return addr - wl->part.mem.start;
|
||||
wl->if_ops->disable_irq(wl);
|
||||
}
|
||||
|
||||
void wl1271_enable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
wl->if_ops->enable_irq(wl);
|
||||
}
|
||||
|
||||
/* Set the SPI partitions to access the chip addresses
|
||||
|
@ -117,54 +116,12 @@ int wl1271_set_partition(struct wl1271 *wl,
|
|||
|
||||
void wl1271_io_reset(struct wl1271 *wl)
|
||||
{
|
||||
wl1271_spi_reset(wl);
|
||||
wl->if_ops->reset(wl);
|
||||
}
|
||||
|
||||
void wl1271_io_init(struct wl1271 *wl)
|
||||
{
|
||||
wl1271_spi_init(wl);
|
||||
}
|
||||
|
||||
void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl1271_spi_raw_write(wl, addr, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl1271_spi_raw_read(wl, addr, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_spi_raw_read(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_spi_raw_write(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
u32 wl1271_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
|
||||
}
|
||||
|
||||
void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
|
||||
{
|
||||
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
|
||||
wl->if_ops->init(wl);
|
||||
}
|
||||
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
|
||||
|
|
|
@ -25,31 +25,49 @@
|
|||
#ifndef __WL1271_IO_H__
|
||||
#define __WL1271_IO_H__
|
||||
|
||||
#include "wl1271_reg.h"
|
||||
|
||||
#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
|
||||
|
||||
#define HW_PARTITION_REGISTERS_ADDR 0x1FFC0
|
||||
#define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR)
|
||||
#define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4)
|
||||
#define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8)
|
||||
#define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12)
|
||||
#define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16)
|
||||
#define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20)
|
||||
#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24)
|
||||
|
||||
#define HW_ACCESS_REGISTER_SIZE 4
|
||||
|
||||
#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
|
||||
|
||||
struct wl1271;
|
||||
|
||||
void wl1271_disable_interrupts(struct wl1271 *wl);
|
||||
void wl1271_enable_interrupts(struct wl1271 *wl);
|
||||
|
||||
void wl1271_io_reset(struct wl1271 *wl);
|
||||
void wl1271_io_init(struct wl1271 *wl);
|
||||
|
||||
static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl)
|
||||
{
|
||||
return wl->if_ops->dev(wl);
|
||||
}
|
||||
|
||||
|
||||
/* Raw target IO, address is not translated */
|
||||
void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed);
|
||||
void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed);
|
||||
static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl->if_ops->write(wl, addr, buf, len, fixed);
|
||||
}
|
||||
|
||||
/* Translated target IO */
|
||||
void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
u32 wl1271_read32(struct wl1271 *wl, int addr);
|
||||
void wl1271_write32(struct wl1271 *wl, int addr, u32 val);
|
||||
|
||||
/* Top Register IO */
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
|
||||
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
|
||||
|
||||
int wl1271_set_partition(struct wl1271 *wl,
|
||||
struct wl1271_partition_set *p);
|
||||
static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl->if_ops->read(wl, addr, buf, len, fixed);
|
||||
}
|
||||
|
||||
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
|
@ -65,4 +83,74 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
|
|||
wl1271_raw_write(wl, addr, &wl->buffer_32,
|
||||
sizeof(wl->buffer_32), false);
|
||||
}
|
||||
|
||||
/* Translated target IO */
|
||||
static inline int wl1271_translate_addr(struct wl1271 *wl, int addr)
|
||||
{
|
||||
/*
|
||||
* To translate, first check to which window of addresses the
|
||||
* particular address belongs. Then subtract the starting address
|
||||
* of that window from the address. Then, add offset of the
|
||||
* translated region.
|
||||
*
|
||||
* The translated regions occur next to each other in physical device
|
||||
* memory, so just add the sizes of the preceeding address regions to
|
||||
* get the offset to the new region.
|
||||
*
|
||||
* Currently, only the two first regions are addressed, and the
|
||||
* assumption is that all addresses will fall into either of those
|
||||
* two.
|
||||
*/
|
||||
if ((addr >= wl->part.reg.start) &&
|
||||
(addr < wl->part.reg.start + wl->part.reg.size))
|
||||
return addr - wl->part.reg.start + wl->part.mem.size;
|
||||
else
|
||||
return addr - wl->part.mem.start;
|
||||
}
|
||||
|
||||
static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_raw_read(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_raw_write(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
|
||||
}
|
||||
|
||||
static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
|
||||
{
|
||||
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
|
||||
}
|
||||
|
||||
|
||||
/* Top Register IO */
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
|
||||
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
|
||||
|
||||
int wl1271_set_partition(struct wl1271 *wl,
|
||||
struct wl1271_partition_set *p);
|
||||
|
||||
/* Functions from wl1271_main.c */
|
||||
|
||||
int wl1271_register_hw(struct wl1271 *wl);
|
||||
int wl1271_init_ieee80211(struct wl1271 *wl);
|
||||
struct ieee80211_hw *wl1271_alloc_hw(void);
|
||||
int wl1271_free_hw(struct wl1271 *wl);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,22 +22,17 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/spi/wl12xx.h>
|
||||
#include <linux/inetdevice.h>
|
||||
|
||||
#include "wl1271.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_event.h"
|
||||
#include "wl1271_tx.h"
|
||||
|
@ -364,11 +359,6 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void wl1271_disable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
disable_irq(wl->irq);
|
||||
}
|
||||
|
||||
static void wl1271_power_off(struct wl1271 *wl)
|
||||
{
|
||||
wl->set_power(false);
|
||||
|
@ -384,10 +374,11 @@ static void wl1271_power_on(struct wl1271 *wl)
|
|||
static void wl1271_fw_status(struct wl1271 *wl,
|
||||
struct wl1271_fw_status *status)
|
||||
{
|
||||
struct timespec ts;
|
||||
u32 total = 0;
|
||||
int i;
|
||||
|
||||
wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
|
||||
wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
|
||||
|
||||
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
|
||||
"drv_rx_counter = %d, tx_results_counter = %d)",
|
||||
|
@ -412,14 +403,19 @@ static void wl1271_fw_status(struct wl1271 *wl,
|
|||
ieee80211_queue_work(wl->hw, &wl->tx_work);
|
||||
|
||||
/* update the host-chipset time offset */
|
||||
wl->time_offset = jiffies_to_usecs(jiffies) -
|
||||
le32_to_cpu(status->fw_localtime);
|
||||
getnstimeofday(&ts);
|
||||
wl->time_offset = (timespec_to_ns(&ts) >> 10) -
|
||||
(s64)le32_to_cpu(status->fw_localtime);
|
||||
}
|
||||
|
||||
#define WL1271_IRQ_MAX_LOOPS 10
|
||||
|
||||
static void wl1271_irq_work(struct work_struct *work)
|
||||
{
|
||||
int ret;
|
||||
u32 intr;
|
||||
int loopcount = WL1271_IRQ_MAX_LOOPS;
|
||||
unsigned long flags;
|
||||
struct wl1271 *wl =
|
||||
container_of(work, struct wl1271, irq_work);
|
||||
|
||||
|
@ -427,91 +423,77 @@ static void wl1271_irq_work(struct work_struct *work)
|
|||
|
||||
wl1271_debug(DEBUG_IRQ, "IRQ work");
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl, true);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) {
|
||||
clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
loopcount--;
|
||||
|
||||
wl1271_fw_status(wl, wl->fw_status);
|
||||
intr = le32_to_cpu(wl->fw_status->intr);
|
||||
if (!intr) {
|
||||
wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
|
||||
goto out_sleep;
|
||||
wl1271_fw_status(wl, wl->fw_status);
|
||||
intr = le32_to_cpu(wl->fw_status->intr);
|
||||
if (!intr) {
|
||||
wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
|
||||
continue;
|
||||
}
|
||||
|
||||
intr &= WL1271_INTR_MASK;
|
||||
|
||||
if (intr & WL1271_ACX_INTR_DATA) {
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
|
||||
|
||||
/* check for tx results */
|
||||
if (wl->fw_status->tx_results_counter !=
|
||||
(wl->tx_results_count & 0xff))
|
||||
wl1271_tx_complete(wl);
|
||||
|
||||
wl1271_rx(wl, wl->fw_status);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_EVENT_A) {
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
|
||||
wl1271_event_handle(wl, 0);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_EVENT_B) {
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
|
||||
wl1271_event_handle(wl, 1);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
|
||||
wl1271_debug(DEBUG_IRQ,
|
||||
"WL1271_ACX_INTR_INIT_COMPLETE");
|
||||
|
||||
if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
|
||||
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
}
|
||||
|
||||
intr &= WL1271_INTR_MASK;
|
||||
if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags))
|
||||
ieee80211_queue_work(wl->hw, &wl->irq_work);
|
||||
else
|
||||
clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
if (intr & WL1271_ACX_INTR_EVENT_A) {
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
|
||||
wl1271_event_handle(wl, 0);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_EVENT_B) {
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
|
||||
wl1271_event_handle(wl, 1);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
|
||||
wl1271_debug(DEBUG_IRQ,
|
||||
"WL1271_ACX_INTR_INIT_COMPLETE");
|
||||
|
||||
if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
|
||||
|
||||
if (intr & WL1271_ACX_INTR_DATA) {
|
||||
u8 tx_res_cnt = wl->fw_status->tx_results_counter -
|
||||
wl->tx_results_count;
|
||||
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
|
||||
|
||||
/* check for tx results */
|
||||
if (tx_res_cnt)
|
||||
wl1271_tx_complete(wl, tx_res_cnt);
|
||||
|
||||
wl1271_rx(wl, wl->fw_status);
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static irqreturn_t wl1271_irq(int irq, void *cookie)
|
||||
{
|
||||
struct wl1271 *wl;
|
||||
unsigned long flags;
|
||||
|
||||
wl1271_debug(DEBUG_IRQ, "IRQ");
|
||||
|
||||
wl = cookie;
|
||||
|
||||
/* complete the ELP completion */
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
if (wl->elp_compl) {
|
||||
complete(wl->elp_compl);
|
||||
wl->elp_compl = NULL;
|
||||
}
|
||||
|
||||
ieee80211_queue_work(wl->hw, &wl->irq_work);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int wl1271_fetch_firmware(struct wl1271 *wl)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev);
|
||||
ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl));
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_error("could not get firmware: %d", ret);
|
||||
|
@ -583,7 +565,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
|
|||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev);
|
||||
ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl));
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_error("could not get nvs file: %d", ret);
|
||||
|
@ -825,15 +807,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
* The workqueue is slow to process the tx_queue and we need stop
|
||||
* the queue here, otherwise the queue will get too long.
|
||||
*/
|
||||
if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) {
|
||||
ieee80211_stop_queues(wl->hw);
|
||||
if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
|
||||
wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
|
||||
|
||||
/*
|
||||
* FIXME: this is racy, the variable is not properly
|
||||
* protected. Maybe fix this by removing the stupid
|
||||
* variable altogether and checking the real queue state?
|
||||
*/
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
ieee80211_stop_queues(wl->hw);
|
||||
set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
@ -1040,8 +1020,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|||
wl->tx_results_count = 0;
|
||||
wl->tx_packets_count = 0;
|
||||
wl->tx_security_last_seq = 0;
|
||||
wl->tx_security_seq_16 = 0;
|
||||
wl->tx_security_seq_32 = 0;
|
||||
wl->tx_security_seq = 0;
|
||||
wl->time_offset = 0;
|
||||
wl->session_counter = 0;
|
||||
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
|
@ -1127,7 +1106,7 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
|
|||
|
||||
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_join(wl);
|
||||
ret = wl1271_cmd_join(wl, wl->bss_type);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
|
@ -1176,17 +1155,16 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel)
|
|||
static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
|
||||
0xad, 0xbe, 0xef };
|
||||
|
||||
/* the dummy join is not required for ad-hoc */
|
||||
if (wl->bss_type == BSS_TYPE_IBSS)
|
||||
goto out;
|
||||
|
||||
/* disable mac filter, so we hear everything */
|
||||
wl->rx_config &= ~CFG_BSSID_FILTER_EN;
|
||||
|
||||
wl->channel = channel;
|
||||
memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_join(wl);
|
||||
/* the dummy join is performed always with STATION BSS type to allow
|
||||
also ad-hoc mode to listen to the surroundings without sending any
|
||||
beacons yet. */
|
||||
ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -1255,7 +1233,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
|
||||
wl->channel = channel;
|
||||
/* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
|
||||
ret = wl1271_cmd_join(wl);
|
||||
ret = wl1271_cmd_join(wl, wl->bss_type);
|
||||
if (ret < 0)
|
||||
wl1271_warning("cmd join to update channel failed %d",
|
||||
ret);
|
||||
|
@ -1272,13 +1250,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
* through the bss_info_changed() hook.
|
||||
*/
|
||||
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
|
||||
wl1271_info("psm enabled");
|
||||
wl1271_debug(DEBUG_PSM, "psm enabled");
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
|
||||
true);
|
||||
}
|
||||
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
|
||||
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||
wl1271_info("psm disabled");
|
||||
wl1271_debug(DEBUG_PSM, "psm disabled");
|
||||
|
||||
clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
|
||||
|
||||
|
@ -1449,15 +1427,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
key_type = KEY_TKIP;
|
||||
|
||||
key_conf->hw_key_idx = key_conf->keyidx;
|
||||
tx_seq_32 = wl->tx_security_seq_32;
|
||||
tx_seq_16 = wl->tx_security_seq_16;
|
||||
tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
|
||||
tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
|
||||
break;
|
||||
case ALG_CCMP:
|
||||
key_type = KEY_AES;
|
||||
|
||||
key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
tx_seq_32 = wl->tx_security_seq_32;
|
||||
tx_seq_16 = wl->tx_security_seq_16;
|
||||
tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
|
||||
tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
|
||||
break;
|
||||
default:
|
||||
wl1271_error("Unknown key algo 0x%x", key_conf->alg);
|
||||
|
@ -1738,7 +1716,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
if (do_join) {
|
||||
ret = wl1271_cmd_join(wl);
|
||||
ret = wl1271_cmd_join(wl, wl->bss_type);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd join failed %d", ret);
|
||||
goto out_sleep;
|
||||
|
@ -1959,7 +1937,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
|||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
static int wl1271_register_hw(struct wl1271 *wl)
|
||||
int wl1271_register_hw(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1980,8 +1958,9 @@ static int wl1271_register_hw(struct wl1271 *wl)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wl1271_register_hw);
|
||||
|
||||
static int wl1271_init_ieee80211(struct wl1271 *wl)
|
||||
int wl1271_init_ieee80211(struct wl1271 *wl)
|
||||
{
|
||||
/* The tx descriptor buffer and the TKIP space. */
|
||||
wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
|
||||
|
@ -1994,7 +1973,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM |
|
||||
IEEE80211_HW_BEACON_FILTER |
|
||||
IEEE80211_HW_SUPPORTS_PS;
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_HAS_RATE_CONTROL;
|
||||
|
||||
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
@ -2004,29 +1984,15 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
if (wl1271_11a_enabled())
|
||||
wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
|
||||
|
||||
SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
|
||||
SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl1271_device_release(struct device *dev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static struct platform_device wl1271_device = {
|
||||
.name = "wl1271",
|
||||
.id = -1,
|
||||
|
||||
/* device model insists to have a release function */
|
||||
.dev = {
|
||||
.release = wl1271_device_release,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
|
||||
|
||||
#define WL1271_DEFAULT_CHANNEL 0
|
||||
|
||||
static struct ieee80211_hw *wl1271_alloc_hw(void)
|
||||
struct ieee80211_hw *wl1271_alloc_hw(void)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl1271 *wl;
|
||||
|
@ -2073,8 +2039,11 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
|
|||
/* Apply default driver configuration. */
|
||||
wl1271_conf_init(wl);
|
||||
|
||||
wl1271_debugfs_init(wl);
|
||||
|
||||
return hw;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
|
||||
|
||||
int wl1271_free_hw(struct wl1271 *wl)
|
||||
{
|
||||
|
@ -2095,145 +2064,8 @@ int wl1271_free_hw(struct wl1271 *wl)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
{
|
||||
struct wl12xx_platform_data *pdata;
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl1271 *wl;
|
||||
int ret;
|
||||
|
||||
pdata = spi->dev.platform_data;
|
||||
if (!pdata) {
|
||||
wl1271_error("no platform data");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hw = wl1271_alloc_hw();
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
wl = hw->priv;
|
||||
|
||||
dev_set_drvdata(&spi->dev, wl);
|
||||
wl->spi = spi;
|
||||
|
||||
/* This is the only SPI value that we need to set here, the rest
|
||||
* comes from the board-peripherals file */
|
||||
spi->bits_per_word = 32;
|
||||
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
wl1271_error("spi_setup failed");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
wl->set_power = pdata->set_power;
|
||||
if (!wl->set_power) {
|
||||
wl1271_error("set power function missing in platform data");
|
||||
ret = -ENODEV;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
wl->irq = spi->irq;
|
||||
if (wl->irq < 0) {
|
||||
wl1271_error("irq missing in platform data");
|
||||
ret = -ENODEV;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("request_irq() failed: %d", ret);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
|
||||
|
||||
disable_irq(wl->irq);
|
||||
|
||||
ret = platform_device_register(&wl1271_device);
|
||||
if (ret) {
|
||||
wl1271_error("couldn't register platform device");
|
||||
goto out_irq;
|
||||
}
|
||||
dev_set_drvdata(&wl1271_device.dev, wl);
|
||||
|
||||
ret = wl1271_init_ieee80211(wl);
|
||||
if (ret)
|
||||
goto out_platform;
|
||||
|
||||
ret = wl1271_register_hw(wl);
|
||||
if (ret)
|
||||
goto out_platform;
|
||||
|
||||
wl1271_debugfs_init(wl);
|
||||
|
||||
wl1271_notice("initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
out_platform:
|
||||
platform_device_unregister(&wl1271_device);
|
||||
|
||||
out_irq:
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
out_free:
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit wl1271_remove(struct spi_device *spi)
|
||||
{
|
||||
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
|
||||
|
||||
platform_device_unregister(&wl1271_device);
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
wl1271_free_hw(wl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct spi_driver wl1271_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wl1271",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = wl1271_probe,
|
||||
.remove = __devexit_p(wl1271_remove),
|
||||
};
|
||||
|
||||
static int __init wl1271_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = spi_register_driver(&wl1271_spi_driver);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to register spi driver: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit wl1271_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&wl1271_spi_driver);
|
||||
|
||||
wl1271_notice("unloaded");
|
||||
}
|
||||
|
||||
module_init(wl1271_init);
|
||||
module_exit(wl1271_exit);
|
||||
EXPORT_SYMBOL_GPL(wl1271_free_hw);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL1271_FW_NAME);
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_ps.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
#define WL1271_WAKEUP_TIMEOUT 500
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "wl1271_acx.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_rx.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
|
||||
|
@ -160,6 +159,13 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
|
|||
u8 *buf;
|
||||
u8 beacon = 0;
|
||||
|
||||
/*
|
||||
* In PLT mode we seem to get frames and mac80211 warns about them,
|
||||
* workaround this by not retrieving them at all.
|
||||
*/
|
||||
if (unlikely(wl->state == WL1271_STATE_PLT))
|
||||
return;
|
||||
|
||||
skb = __dev_alloc_skb(length, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
wl1271_error("Couldn't allocate RX frame");
|
||||
|
@ -218,6 +224,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
|
|||
|
||||
wl->rx_counter++;
|
||||
drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||
}
|
||||
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 2009-2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/crc7.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <plat/gpio.h>
|
||||
|
||||
#include "wl1271.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
|
||||
#define RX71_WL1271_IRQ_GPIO 42
|
||||
|
||||
#ifndef SDIO_VENDOR_ID_TI
|
||||
#define SDIO_VENDOR_ID_TI 0x0097
|
||||
#endif
|
||||
|
||||
#ifndef SDIO_DEVICE_ID_TI_WL1271
|
||||
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
|
||||
#endif
|
||||
|
||||
static const struct sdio_device_id wl1271_devices[] = {
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, wl1271_devices);
|
||||
|
||||
static inline struct sdio_func *wl_to_func(struct wl1271 *wl)
|
||||
{
|
||||
return wl->if_priv;
|
||||
}
|
||||
|
||||
static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
|
||||
{
|
||||
return &(wl_to_func(wl)->dev);
|
||||
}
|
||||
|
||||
static irqreturn_t wl1271_irq(int irq, void *cookie)
|
||||
{
|
||||
struct wl1271 *wl = cookie;
|
||||
unsigned long flags;
|
||||
|
||||
wl1271_debug(DEBUG_IRQ, "IRQ");
|
||||
|
||||
/* complete the ELP completion */
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
if (wl->elp_compl) {
|
||||
complete(wl->elp_compl);
|
||||
wl->elp_compl = NULL;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
|
||||
ieee80211_queue_work(wl->hw, &wl->irq_work);
|
||||
set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
disable_irq(wl->irq);
|
||||
}
|
||||
|
||||
static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
enable_irq(wl->irq);
|
||||
}
|
||||
|
||||
static void wl1271_sdio_reset(struct wl1271 *wl)
|
||||
{
|
||||
}
|
||||
|
||||
static void wl1271_sdio_init(struct wl1271 *wl)
|
||||
{
|
||||
}
|
||||
|
||||
static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
int ret;
|
||||
struct sdio_func *func = wl_to_func(wl);
|
||||
|
||||
sdio_claim_host(func);
|
||||
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
|
||||
((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
|
||||
wl1271_debug(DEBUG_SPI, "sdio read 52 addr 0x%x, byte 0x%02x",
|
||||
addr, ((u8 *)buf)[0]);
|
||||
} else {
|
||||
if (fixed)
|
||||
ret = sdio_readsb(func, buf, addr, len);
|
||||
else
|
||||
ret = sdio_memcpy_fromio(func, buf, addr, len);
|
||||
|
||||
wl1271_debug(DEBUG_SPI, "sdio read 53 addr 0x%x, %d bytes",
|
||||
addr, len);
|
||||
wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
wl1271_error("sdio read failed (%d)", ret);
|
||||
|
||||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
int ret;
|
||||
struct sdio_func *func = wl_to_func(wl);
|
||||
|
||||
sdio_claim_host(func);
|
||||
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
|
||||
sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
|
||||
wl1271_debug(DEBUG_SPI, "sdio write 52 addr 0x%x, byte 0x%02x",
|
||||
addr, ((u8 *)buf)[0]);
|
||||
} else {
|
||||
wl1271_debug(DEBUG_SPI, "sdio write 53 addr 0x%x, %d bytes",
|
||||
addr, len);
|
||||
wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len);
|
||||
|
||||
if (fixed)
|
||||
ret = sdio_writesb(func, addr, buf, len);
|
||||
else
|
||||
ret = sdio_memcpy_toio(func, addr, buf, len);
|
||||
}
|
||||
if (ret)
|
||||
wl1271_error("sdio write failed (%d)", ret);
|
||||
|
||||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
static struct wl1271_if_operations sdio_ops = {
|
||||
.read = wl1271_sdio_raw_read,
|
||||
.write = wl1271_sdio_raw_write,
|
||||
.reset = wl1271_sdio_reset,
|
||||
.init = wl1271_sdio_init,
|
||||
.dev = wl1271_sdio_wl_to_dev,
|
||||
.enable_irq = wl1271_sdio_enable_interrupts,
|
||||
.disable_irq = wl1271_sdio_disable_interrupts
|
||||
};
|
||||
|
||||
static void wl1271_sdio_set_power(bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
static int __devinit wl1271_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl1271 *wl;
|
||||
int ret;
|
||||
|
||||
/* We are only able to handle the wlan function */
|
||||
if (func->num != 0x02)
|
||||
return -ENODEV;
|
||||
|
||||
hw = wl1271_alloc_hw();
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
wl = hw->priv;
|
||||
|
||||
wl->if_priv = func;
|
||||
wl->if_ops = &sdio_ops;
|
||||
|
||||
wl->set_power = wl1271_sdio_set_power;
|
||||
|
||||
/* Grab access to FN0 for ELP reg. */
|
||||
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
|
||||
|
||||
wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO);
|
||||
if (wl->irq < 0) {
|
||||
ret = wl->irq;
|
||||
wl1271_error("could not get irq!");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("request_irq() failed: %d", ret);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
|
||||
|
||||
disable_irq(wl->irq);
|
||||
|
||||
ret = wl1271_init_ieee80211(wl);
|
||||
if (ret)
|
||||
goto out_irq;
|
||||
|
||||
ret = wl1271_register_hw(wl);
|
||||
if (ret)
|
||||
goto out_irq;
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_set_drvdata(func, wl);
|
||||
|
||||
ret = sdio_enable_func(func);
|
||||
if (ret)
|
||||
goto out_release;
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
wl1271_notice("initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
out_release:
|
||||
sdio_release_host(func);
|
||||
|
||||
out_irq:
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
|
||||
out_free:
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit wl1271_remove(struct sdio_func *func)
|
||||
{
|
||||
struct wl1271 *wl = sdio_get_drvdata(func);
|
||||
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_disable_func(func);
|
||||
sdio_release_host(func);
|
||||
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
kfree(wl->target_mem_map);
|
||||
vfree(wl->fw);
|
||||
wl->fw = NULL;
|
||||
kfree(wl->nvs);
|
||||
wl->nvs = NULL;
|
||||
|
||||
kfree(wl->fw_status);
|
||||
kfree(wl->tx_res_if);
|
||||
|
||||
ieee80211_free_hw(wl->hw);
|
||||
}
|
||||
|
||||
static struct sdio_driver wl1271_sdio_driver = {
|
||||
.name = "wl1271",
|
||||
.id_table = wl1271_devices,
|
||||
.probe = wl1271_probe,
|
||||
.remove = __devexit_p(wl1271_remove),
|
||||
};
|
||||
|
||||
static int __init wl1271_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sdio_register_driver(&wl1271_sdio_driver);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to register sdio driver: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit wl1271_exit(void)
|
||||
{
|
||||
sdio_unregister_driver(&wl1271_sdio_driver);
|
||||
|
||||
wl1271_notice("unloaded");
|
||||
}
|
||||
|
||||
module_init(wl1271_init);
|
||||
module_exit(wl1271_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL1271_FW_NAME);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue