Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
a1870b9c
Commit
a1870b9c
authored
Jun 16, 2009
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
parents
6cc90a5a
1fa6f4af
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
304 additions
and
297 deletions
+304
-297
Documentation/rfkill.txt
Documentation/rfkill.txt
+69
-68
drivers/net/wireless/ath/ath5k/pcu.c
drivers/net/wireless/ath/ath5k/pcu.c
+3
-2
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/Kconfig
+0
-1
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/ath9k.h
+1
-9
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.c
+13
-16
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/hw.h
+0
-3
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/main.c
+41
-89
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/recv.c
+1
-0
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.c
+0
-1
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.c
+86
-55
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
+1
-3
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/if_spi.c
+6
-5
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-laptop.c
+1
-1
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/sony-laptop.c
+3
-2
net/mac80211/debugfs.c
net/mac80211/debugfs.c
+25
-0
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+1
-1
net/mac80211/mlme.c
net/mac80211/mlme.c
+26
-12
net/mac80211/util.c
net/mac80211/util.c
+0
-25
net/mac80211/wext.c
net/mac80211/wext.c
+27
-4
No files found.
Documentation/rfkill.txt
View file @
a1870b9c
...
...
@@ -3,9 +3,8 @@ rfkill - RF kill switch support
1. Introduction
2. Implementation details
3. Kernel driver guidelines
4. Kernel API
5. Userspace support
3. Kernel API
4. Userspace support
1. Introduction
...
...
@@ -19,82 +18,62 @@ disable all transmitters of a certain type (or all). This is intended for
situations where transmitters need to be turned off, for example on
aircraft.
The rfkill subsystem has a concept of "hard" and "soft" block, which
differ little in their meaning (block == transmitters off) but rather in
whether they can be changed or not:
- hard block: read-only radio block that cannot be overriden by software
- soft block: writable radio block (need not be readable) that is set by
the system software.
2. Implementation details
The rfkill subsystem is composed of various components: the rfkill class, the
rfkill-input module (an input layer handler), and some specific input layer
events.
The rfkill class is provided for kernel drivers to register their radio
transmitter with the kernel, provide methods for turning it on and off and,
optionally, letting the system know about hardware-disabled states that may
be implemented on the device. This code is enabled with the CONFIG_RFKILL
Kconfig option, which drivers can "select".
The rfkill class code also notifies userspace of state changes, this is
achieved via uevents. It also provides some sysfs files for userspace to
check the status of radio transmitters. See the "Userspace support" section
below.
The rfkill subsystem is composed of three main components:
* the rfkill core,
* the deprecated rfkill-input module (an input layer handler, being
replaced by userspace policy code) and
* the rfkill drivers.
The rfkill core provides API for kernel drivers to register their radio
transmitter with the kernel, methods for turning it on and off and, letting
the system know about hardware-disabled states that may be implemented on
the device.
The rfkill-input code implements a basic response to rfkill buttons -- it
implements turning on/off all devices of a certain class (or all).
The rfkill core code also notifies userspace of state changes, and provides
ways for userspace to query the current states. See the "Userspace support"
section below.
When the device is hard-blocked (either by a call to rfkill_set_hw_state()
or from query_hw_block) set_block() will be invoked but drivers can well
ignore the method call since they can use the return value of the function
rfkill_set_hw_state() to sync the software state instead of keeping track
of calls to set_block().
The entire functionality is spread over more than one subsystem:
* The kernel input layer generates KEY_WWAN, KEY_WLAN etc. and
SW_RFKILL_ALL -- when the user presses a button. Drivers for radio
transmitters generally do not register to the input layer, unless the
device really provides an input device (i.e. a button that has no
effect other than generating a button press event)
* The rfkill-input code hooks up to these events and switches the soft-block
of the various radio transmitters, depending on the button type.
* The rfkill drivers turn off/on their transmitters as requested.
* The rfkill class will generate userspace notifications (uevents) to tell
userspace what the current state is.
or from query_hw_block) set_block() will be invoked for additional software
block, but drivers can ignore the method call since they can use the return
value of the function rfkill_set_hw_state() to sync the software state
instead of keeping track of calls to set_block(). In fact, drivers should
use the return value of rfkill_set_hw_state() unless the hardware actually
keeps track of soft and hard block separately.
3. Kernel API
3. Kernel driver guidelines
Drivers for radio transmitters normally implement only the rfkill class.
These drivers may not unblock the transmitter based on own decisions, they
should act on information provided by the rfkill class only.
Drivers for radio transmitters normally implement an rfkill driver.
Platform drivers might implement input devices if the rfkill button is just
that, a button. If that button influences the hardware then you need to
implement an rfkill
class
instead. This also applies if the platform provides
implement an rfkill
driver
instead. This also applies if the platform provides
a way to turn on/off the transmitter(s).
During suspend/hibernation, transmitters should only be left enabled when
wake-on wlan or similar functionality requires it and the device wasn't
blocked before suspend/hibernate. Note that it may be necessary to update
the rfkill subsystem's idea of what the current state is at resume time if
the state may have changed over suspend.
For some platforms, it is possible that the hardware state changes during
suspend/hibernation, in which case it will be necessary to update the rfkill
core with the current state is at resume time.
To create an rfkill driver, driver's Kconfig needs to have
4. Kernel API
depends on RFKILL || !RFKILL
To build a driver with rfkill subsystem support, the driver should depend on
(or select) the Kconfig symbol RFKILL.
The hardware the driver talks to may be write-only (where the current state
of the hardware is unknown), or read-write (where the hardware can be queried
about its current state).
to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL
case allows the driver to be built when rfkill is not configured, which which
case all rfkill API can still be used but will be provided by static inlines
which compile to almost nothing.
Calling rfkill_set_hw_state() when a state change happens is required from
rfkill drivers that control devices that can be hard-blocked unless they also
...
...
@@ -105,10 +84,33 @@ device). Don't do this unless you cannot get the event in any other way.
5. Userspace support
The following sysfs entries exist for every rfkill device:
The recommended userspace interface to use is /dev/rfkill, which is a misc
character device that allows userspace to obtain and set the state of rfkill
devices and sets of devices. It also notifies userspace about device addition
and removal. The API is a simple read/write API that is defined in
linux/rfkill.h, with one ioctl that allows turning off the deprecated input
handler in the kernel for the transition period.
Except for the one ioctl, communication with the kernel is done via read()
and write() of instances of 'struct rfkill_event'. In this structure, the
soft and hard block are properly separated (unlike sysfs, see below) and
userspace is able to get a consistent snapshot of all rfkill devices in the
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.
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 there has the
following attributes:
name: Name assigned by driver to this key (interface or driver name).
type:
Name of the key type
("wlan", "bluetooth", etc).
type:
Driver type string
("wlan", "bluetooth", etc).
state: Current state of the transmitter
0: RFKILL_STATE_SOFT_BLOCKED
transmitter is turned off by software
...
...
@@ -117,7 +119,12 @@ The following sysfs entries exist for every rfkill device:
2: RFKILL_STATE_HARD_BLOCKED
transmitter is forced off by something outside of
the driver's control.
claim: 0: Kernel handles events (currently always reads that value)
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:
...
...
@@ -128,9 +135,3 @@ RFKILL_TYPE
The contents of these variables corresponds to the "name", "state" and
"type" sysfs files explained above.
An alternative userspace interface exists as a misc device /dev/rfkill,
which allows userspace to obtain and set the state of rfkill devices and
sets of devices. It also notifies userspace about device addition and
removal. The API is a simple read/write API that is defined in
linux/rfkill.h.
drivers/net/wireless/ath/ath5k/pcu.c
View file @
a1870b9c
...
...
@@ -733,8 +733,9 @@ 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 mode zero timer0 to start TSF */
if
(
ah
->
ah_op_mode
==
NL80211_IFTYPE_AP
)
/* 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
)
ath5k_hw_reg_write
(
ah
,
0
,
AR5K_TIMER0
);
ath5k_hw_reg_write
(
ah
,
next_beacon
,
AR5K_TIMER0
);
...
...
drivers/net/wireless/ath/ath9k/Kconfig
View file @
a1870b9c
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
depends on RFKILL || RFKILL=n
select ATH_COMMON
select MAC80211_LEDS
select LEDS_CLASS
...
...
drivers/net/wireless/ath/ath9k/ath9k.h
View file @
a1870b9c
...
...
@@ -21,7 +21,6 @@
#include <linux/device.h>
#include <net/mac80211.h>
#include <linux/leds.h>
#include <linux/rfkill.h>
#include "hw.h"
#include "rc.h"
...
...
@@ -460,12 +459,6 @@ struct ath_led {
bool
registered
;
};
struct
ath_rfkill
{
struct
rfkill
*
rfkill
;
struct
rfkill_ops
ops
;
char
rfkill_name
[
32
];
};
/********************/
/* Main driver core */
/********************/
...
...
@@ -505,7 +498,6 @@ struct ath_rfkill {
#define SC_OP_PROTECT_ENABLE BIT(6)
#define SC_OP_RXFLUSH BIT(7)
#define SC_OP_LED_ASSOCIATED BIT(8)
#define SC_OP_RFKILL_REGISTERED BIT(9)
#define SC_OP_WAIT_FOR_BEACON BIT(12)
#define SC_OP_LED_ON BIT(13)
#define SC_OP_SCANNING BIT(14)
...
...
@@ -591,7 +583,6 @@ struct ath_softc {
int
beacon_interval
;
struct
ath_rfkill
rf_kill
;
struct
ath_ani
ani
;
struct
ath9k_node_stats
nodestats
;
#ifdef CONFIG_ATH9K_DEBUG
...
...
@@ -677,6 +668,7 @@ static inline void ath9k_ps_restore(struct ath_softc *sc)
if
(
atomic_dec_and_test
(
&
sc
->
ps_usecount
))
if
((
sc
->
hw
->
conf
.
flags
&
IEEE80211_CONF_PS
)
&&
!
(
sc
->
sc_flags
&
(
SC_OP_WAIT_FOR_BEACON
|
SC_OP_WAIT_FOR_CAB
|
SC_OP_WAIT_FOR_PSPOLL_DATA
|
SC_OP_WAIT_FOR_TX_ACK
)))
ath9k_hw_setpower
(
sc
->
sc_ah
,
...
...
drivers/net/wireless/ath/ath9k/hw.c
View file @
a1870b9c
...
...
@@ -2186,6 +2186,18 @@ static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan
REG_WRITE
(
ah
,
AR_PHY_MASK2_P_61_45
,
tmp_mask
);
}
static
void
ath9k_enable_rfkill
(
struct
ath_hw
*
ah
)
{
REG_SET_BIT
(
ah
,
AR_GPIO_INPUT_EN_VAL
,
AR_GPIO_INPUT_EN_VAL_RFSILENT_BB
);
REG_CLR_BIT
(
ah
,
AR_GPIO_INPUT_MUX2
,
AR_GPIO_INPUT_MUX2_RFSILENT
);
ath9k_hw_cfg_gpio_input
(
ah
,
ah
->
rfkill_gpio
);
REG_SET_BIT
(
ah
,
AR_PHY_TEST
,
RFSILENT_BB
);
}
int
ath9k_hw_reset
(
struct
ath_hw
*
ah
,
struct
ath9k_channel
*
chan
,
bool
bChannelChange
)
{
...
...
@@ -2313,10 +2325,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_interrupt_masks
(
ah
,
ah
->
opmode
);
ath9k_hw_init_qos
(
ah
);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if
(
ah
->
caps
.
hw_caps
&
ATH9K_HW_CAP_RFSILENT
)
ath9k_enable_rfkill
(
ah
);
#endif
ath9k_hw_init_user_settings
(
ah
);
REG_WRITE
(
ah
,
AR_STA_ID1
,
...
...
@@ -3613,20 +3624,6 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
AR_GPIO_BIT
(
gpio
));
}
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
void
ath9k_enable_rfkill
(
struct
ath_hw
*
ah
)
{
REG_SET_BIT
(
ah
,
AR_GPIO_INPUT_EN_VAL
,
AR_GPIO_INPUT_EN_VAL_RFSILENT_BB
);
REG_CLR_BIT
(
ah
,
AR_GPIO_INPUT_MUX2
,
AR_GPIO_INPUT_MUX2_RFSILENT
);
ath9k_hw_cfg_gpio_input
(
ah
,
ah
->
rfkill_gpio
);
REG_SET_BIT
(
ah
,
AR_PHY_TEST
,
RFSILENT_BB
);
}
#endif
u32
ath9k_hw_getdefantenna
(
struct
ath_hw
*
ah
)
{
return
REG_READ
(
ah
,
AR_DEF_ANTENNA
)
&
0x7
;
...
...
drivers/net/wireless/ath/ath9k/hw.h
View file @
a1870b9c
...
...
@@ -565,9 +565,6 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
void
ath9k_hw_cfg_output
(
struct
ath_hw
*
ah
,
u32
gpio
,
u32
ah_signal_type
);
void
ath9k_hw_set_gpio
(
struct
ath_hw
*
ah
,
u32
gpio
,
u32
val
);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
void
ath9k_enable_rfkill
(
struct
ath_hw
*
ah
);
#endif
u32
ath9k_hw_getdefantenna
(
struct
ath_hw
*
ah
);
void
ath9k_hw_setantenna
(
struct
ath_hw
*
ah
,
u32
antenna
);
bool
ath9k_hw_setantennaswitch
(
struct
ath_hw
*
ah
,
...
...
drivers/net/wireless/ath/ath9k/main.c
View file @
a1870b9c
...
...
@@ -231,6 +231,19 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
}
}
static
struct
ath9k_channel
*
ath_get_curchannel
(
struct
ath_softc
*
sc
,
struct
ieee80211_hw
*
hw
)
{
struct
ieee80211_channel
*
curchan
=
hw
->
conf
.
channel
;
struct
ath9k_channel
*
channel
;
u8
chan_idx
;
chan_idx
=
curchan
->
hw_value
;
channel
=
&
sc
->
sc_ah
->
channels
[
chan_idx
];
ath9k_update_ichannel
(
sc
,
hw
,
channel
);
return
channel
;
}
/*
* Set/change channels. If the channel is really being changed, it's done
* by reseting the chip. To accomplish this we must first cleanup any pending
...
...
@@ -283,7 +296,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
"reset status %d
\n
"
,
channel
->
center_freq
,
r
);
spin_unlock_bh
(
&
sc
->
sc_resetlock
);
return
r
;
goto
ps_restore
;
}
spin_unlock_bh
(
&
sc
->
sc_resetlock
);
...
...
@@ -292,14 +305,17 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
if
(
ath_startrecv
(
sc
)
!=
0
)
{
DPRINTF
(
sc
,
ATH_DBG_FATAL
,
"Unable to restart recv logic
\n
"
);
return
-
EIO
;
r
=
-
EIO
;
goto
ps_restore
;
}
ath_cache_conf_rate
(
sc
,
&
hw
->
conf
);
ath_update_txpow
(
sc
);
ath9k_hw_set_interrupts
(
ah
,
sc
->
imask
);
ps_restore:
ath9k_ps_restore
(
sc
);
return
0
;
return
r
;
}
/*
...
...
@@ -1110,6 +1126,9 @@ void ath_radio_enable(struct ath_softc *sc)
ath9k_ps_wakeup
(
sc
);
ath9k_hw_configpcipowersave
(
ah
,
0
);
if
(
!
ah
->
curchan
)
ah
->
curchan
=
ath_get_curchannel
(
sc
,
sc
->
hw
);
spin_lock_bh
(
&
sc
->
sc_resetlock
);
r
=
ath9k_hw_reset
(
ah
,
ah
->
curchan
,
false
);
if
(
r
)
{
...
...
@@ -1162,6 +1181,9 @@ void ath_radio_disable(struct ath_softc *sc)
ath_stoprecv
(
sc
);
/* turn off frame recv */
ath_flushrecv
(
sc
);
/* flush recv queue */
if
(
!
ah
->
curchan
)
ah
->
curchan
=
ath_get_curchannel
(
sc
,
sc
->
hw
);
spin_lock_bh
(
&
sc
->
sc_resetlock
);
r
=
ath9k_hw_reset
(
ah
,
ah
->
curchan
,
false
);
if
(
r
)
{
...
...
@@ -1178,8 +1200,6 @@ void ath_radio_disable(struct ath_softc *sc)
ath9k_ps_restore
(
sc
);
}
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/*******************/
/* Rfkill */
/*******************/
...
...
@@ -1192,81 +1212,27 @@ static bool ath_is_rfkill_set(struct ath_softc *sc)
ah
->
rfkill_polarity
;
}
/* s/w rfkill handlers */
static
int
ath_rfkill_set_block
(
void
*
data
,
bool
blocked
)
static
void
ath9k_rfkill_poll_state
(
struct
ieee80211_hw
*
hw
)
{
struct
ath_softc
*
sc
=
data
;
if
(
blocked
)
ath_radio_disable
(
sc
);
else
ath_radio_enable
(
sc
);
return
0
;
}
static
void
ath_rfkill_poll_state
(
struct
rfkill
*
rfkill
,
void
*
data
)
{
struct
ath_softc
*
sc
=
data
;
struct
ath_wiphy
*
aphy
=
hw
->
priv
;
struct
ath_softc
*
sc
=
aphy
->
sc
;
bool
blocked
=
!!
ath_is_rfkill_set
(
sc
);
if
(
rfkill_set_hw_state
(
rfkill
,
blocked
))
wiphy_rfkill_set_hw_state
(
hw
->
wiphy
,
blocked
);
if
(
blocked
)
ath_radio_disable
(
sc
);
else
ath_radio_enable
(
sc
);
}
/* Init s/w rfkill */
static
int
ath_init_sw_rfkill
(
struct
ath_softc
*
sc
)
{
sc
->
rf_kill
.
ops
.
set_block
=
ath_rfkill_set_block
;
if
(
sc
->
sc_ah
->
caps
.
hw_caps
&
ATH9K_HW_CAP_RFSILENT
)
sc
->
rf_kill
.
ops
.
poll
=
ath_rfkill_poll_state
;
snprintf
(
sc
->
rf_kill
.
rfkill_name
,
sizeof
(
sc
->
rf_kill
.
rfkill_name
),
"ath9k-%s::rfkill"
,
wiphy_name
(
sc
->
hw
->
wiphy
));
sc
->
rf_kill
.
rfkill
=
rfkill_alloc
(
sc
->
rf_kill
.
rfkill_name
,
wiphy_dev
(
sc
->
hw
->
wiphy
),
RFKILL_TYPE_WLAN
,
&
sc
->
rf_kill
.
ops
,
sc
);
if
(
!
sc
->
rf_kill
.
rfkill
)
{
DPRINTF
(
sc
,
ATH_DBG_FATAL
,
"Failed to allocate rfkill
\n
"
);
return
-
ENOMEM
;
}
return
0
;
}
/* Deinitialize rfkill */
static
void
ath_deinit_rfkill
(
struct
ath_softc
*
sc
)
{
if
(
sc
->
sc_flags
&
SC_OP_RFKILL_REGISTERED
)
{
rfkill_unregister
(
sc
->
rf_kill
.
rfkill
);
rfkill_destroy
(
sc
->
rf_kill
.
rfkill
);
sc
->
sc_flags
&=
~
SC_OP_RFKILL_REGISTERED
;
}
}
static
int
ath_start_rfkill_poll
(
struct
ath_softc
*
sc
)
static
void
ath_start_rfkill_poll
(
struct
ath_softc
*
sc
)
{
if
(
!
(
sc
->
sc_flags
&
SC_OP_RFKILL_REGISTERED
))
{
if
(
rfkill_register
(
sc
->
rf_kill
.
rfkill
))
{
DPRINTF
(
sc
,
ATH_DBG_FATAL
,
"Unable to register rfkill
\n
"
);
rfkill_destroy
(
sc
->
rf_kill
.
rfkill
);
/* Deinitialize the device */
ath_cleanup
(
sc
);
return
-
EIO
;
}
else
{
sc
->
sc_flags
|=
SC_OP_RFKILL_REGISTERED
;
}
}
struct
ath_hw
*
ah
=
sc
->
sc_ah
;
return
0
;
if
(
ah
->
caps
.
hw_caps
&
ATH9K_HW_CAP_RFSILENT
)
wiphy_rfkill_start_polling
(
sc
->
hw
->
wiphy
);
}
#endif
/* CONFIG_RFKILL */
void
ath_cleanup
(
struct
ath_softc
*
sc
)
{
...
...
@@ -1286,9 +1252,6 @@ void ath_detach(struct ath_softc *sc)
DPRINTF
(
sc
,
ATH_DBG_CONFIG
,
"Detach ATH hw
\n
"
);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
ath_deinit_rfkill
(
sc
);
#endif
ath_deinit_leds
(
sc
);
cancel_work_sync
(
&
sc
->
chan_work
);
cancel_delayed_work_sync
(
&
sc
->
wiphy_work
);
...
...
@@ -1626,13 +1589,6 @@ int ath_attach(u16 devid, struct ath_softc *sc)
if
(
error
!=
0
)
goto
error_attach
;
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/* Initialize s/w rfkill */
error
=
ath_init_sw_rfkill
(
sc
);
if
(
error
)
goto
error_attach
;
#endif
INIT_WORK
(
&
sc
->
chan_work
,
ath9k_wiphy_chan_work
);
INIT_DELAYED_WORK
(
&
sc
->
wiphy_work
,
ath9k_wiphy_work
);
sc
->
wiphy_scheduler_int
=
msecs_to_jiffies
(
500
);
...
...
@@ -1648,6 +1604,7 @@ int ath_attach(u16 devid, struct ath_softc *sc)
/* Initialize LED control */
ath_init_leds
(
sc
);
ath_start_rfkill_poll
(
sc
);
return
0
;
...
...
@@ -1920,7 +1877,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
struct
ath_softc
*
sc
=
aphy
->
sc
;
struct
ieee80211_channel
*
curchan
=
hw
->
conf
.
channel
;
struct
ath9k_channel
*
init_channel
;
int
r
,
pos
;
int
r
;
DPRINTF
(
sc
,
ATH_DBG_CONFIG
,
"Starting driver with "
"initial channel: %d MHz
\n
"
,
curchan
->
center_freq
);
...
...
@@ -1950,11 +1907,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
/* setup initial channel */
pos
=
curchan
->
hw_value
;
sc
->
chan_idx
=
curchan
->
hw_value
;
sc
->
chan_idx
=
pos
;
init_channel
=
&
sc
->
sc_ah
->
channels
[
pos
];
ath9k_update_ichannel
(
sc
,
hw
,
init_channel
);
init_channel
=
ath_get_curchannel
(
sc
,
hw
);
/* Reset SERDES registers */
ath9k_hw_configpcipowersave
(
sc
->
sc_ah
,
0
);
...
...
@@ -2018,10 +1973,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
ieee80211_wake_queues
(
hw
);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
r
=
ath_start_rfkill_poll
(
sc
);
#endif
mutex_unlock:
mutex_unlock
(
&
sc
->
mutex
);
...
...
@@ -2159,7 +2110,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
}
else
sc
->
rx
.
rxlink
=
NULL
;
rfkill_pause_polling
(
sc
->
rf_kill
.
rfkill
);
wiphy_rfkill_stop_polling
(
sc
->
hw
->
wiphy
);
/* disable HAL and put h/w to sleep */
ath9k_hw_disable
(
sc
->
sc_ah
);
...
...
@@ -2765,6 +2716,7 @@ struct ieee80211_ops ath9k_ops = {
.
ampdu_action
=
ath9k_ampdu_action
,
.
sw_scan_start
=
ath9k_sw_scan_start
,
.
sw_scan_complete
=
ath9k_sw_scan_complete
,
.
rfkill_poll
=
ath9k_rfkill_poll_state
,
};
static
struct
{
...
...
drivers/net/wireless/ath/ath9k/recv.c
View file @
a1870b9c
...
...
@@ -817,6 +817,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
}
if
(
unlikely
(
sc
->
sc_flags
&
(
SC_OP_WAIT_FOR_BEACON
|
SC_OP_WAIT_FOR_CAB
|
SC_OP_WAIT_FOR_PSPOLL_DATA
)))
ath_rx_ps
(
sc
,
skb
);
...
...
drivers/net/wireless/iwlwifi/iwl-agn.c
View file @
a1870b9c
...
...
@@ -2152,7 +2152,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
/* we should be verifying the device is ready to be opened */
mutex_lock
(
&
priv
->
mutex
);
memset
(
&
priv
->
staging_rxon
,
0
,
sizeof
(
struct
iwl_rxon_cmd
));
/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
* ucode filename and max sizes are card-specific. */
...
...
drivers/net/wireless/iwlwifi/iwl-core.c
View file @
a1870b9c
...
...
@@ -629,13 +629,9 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
if
(
!
sta_ht_inf
->
ht_supported
)
return
0
;
}
if
(
iwl_ht_conf
->
ht_protection
&
IEEE80211_HT_OP_MODE_PROTECTION_20MHZ
)
return
1
;
else
return
iwl_is_channel_extension
(
priv
,
priv
->
band
,
le16_to_cpu
(
priv
->
staging_rxon
.
channel
),
iwl_ht_conf
->
extension_chan_offset
);
return
iwl_is_channel_extension
(
priv
,
priv
->
band
,
le16_to_cpu
(
priv
->
staging_rxon
.
channel
),
iwl_ht_conf
->
extension_chan_offset
);
}
EXPORT_SYMBOL
(
iwl_is_fat_tx_allowed
);
...
...
@@ -826,9 +822,18 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
);
if
(
iwl_is_fat_tx_allowed
(
priv
,
NULL
))
{
/* pure 40 fat */
if
(
rxon
->
flags
&
RXON_FLG_FAT_PROT_MSK
)
if
(
ht_info
->
ht_protection
==
IEEE80211_HT_OP_MODE_PROTECTION_20MHZ
)
{
rxon
->
flags
|=
RXON_FLG_CHANNEL_MODE_PURE_40
;
else
{
/* Note: control channel is opposite of extension channel */
switch
(
ht_info
->
extension_chan_offset
)
{
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
rxon
->
flags
&=
~
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
break
;
case
IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
rxon
->
flags
|=
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK
;
break
;
}
}
else
{
/* Note: control channel is opposite of extension channel */
switch
(
ht_info
->
extension_chan_offset
)
{
case
IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
...
...
@@ -2390,39 +2395,46 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
priv
->
ibss_beacon
=
ieee80211_beacon_get
(
hw
,
vif
);
}
if
((
changes
&
BSS_CHANGED_BSSID
)
&&
!
iwl_is_rfkill
(
priv
))
{
/* If there is currently a HW scan going on in the background
* then we need to cancel it else the RXON below will fail. */
if
(
changes
&
BSS_CHANGED_BEACON_INT
)
{
priv
->
beacon_int
=
bss_conf
->
beacon_int
;
/* TODO: in AP mode, do something to make this take effect */
}
if
(
changes
&
BSS_CHANGED_BSSID
)
{
IWL_DEBUG_MAC80211
(
priv
,
"BSSID %pM
\n
"
,
bss_conf
->
bssid
);
/*
* If there is currently a HW scan going on in the
* background then we need to cancel it else the RXON
* below/in post_associate will fail.
*/
if
(
iwl_scan_cancel_timeout
(
priv
,
100
))
{
IWL_WARN
(
priv
,
"Aborted scan still in progress "
"after 100ms
\n
"
);
IWL_WARN
(
priv
,
"Aborted scan still in progress after 100ms
\n
"
);
IWL_DEBUG_MAC80211
(
priv
,
"leaving - scan abort failed.
\n
"
);
mutex_unlock
(
&
priv
->
mutex
);
return
;
}
memcpy
(
priv
->
staging_rxon
.
bssid_addr
,
bss_conf
->
bssid
,
ETH_ALEN
);
/* TODO: Audit driver for usage of these members and see
* if mac80211 deprecates them (priv->bssid looks like it
* shouldn't be there, but I haven't scanned the IBSS code
* to verify) - jpk */
memcpy
(
priv
->
bssid
,
bss_conf
->
bssid
,
ETH_ALEN
);
if
(
priv
->
iw_mode
==
NL80211_IFTYPE_AP
)
iwlcore_config_ap
(
priv
);
else
{
int
rc
=
iwlcore_commit_rxon
(
priv
);
if
((
priv
->
iw_mode
==
NL80211_IFTYPE_STATION
)
&&
rc
)
iwl_rxon_add_station
(
priv
,
priv
->
active_rxon
.
bssid_addr
,
1
);
/* mac80211 only sets assoc when in STATION mode */
if
(
priv
->
iw_mode
==
NL80211_IFTYPE_ADHOC
||
bss_conf
->
assoc
)
{
memcpy
(
priv
->
staging_rxon
.
bssid_addr
,
bss_conf
->
bssid
,
ETH_ALEN
);
/* currently needed in a few places */
memcpy
(
priv
->
bssid
,
bss_conf
->
bssid
,
ETH_ALEN
);
}
else
{
priv
->
staging_rxon
.
filter_flags
&=
~
RXON_FILTER_ASSOC_MSK
;
}
}
else
if
(
!
iwl_is_rfkill
(
priv
))
{
iwl_scan_cancel_timeout
(
priv
,
100
);
priv
->
staging_rxon
.
filter_flags
&=
~
RXON_FILTER_ASSOC_MSK
;
iwlcore_commit_rxon
(
priv
);
}
/*
* This needs to be after setting the BSSID in case
* mac80211 decides to do both changes at once because
* it will invoke post_associate.
*/
if
(
priv
->
iw_mode
==
NL80211_IFTYPE_ADHOC
&&
changes
&
BSS_CHANGED_BEACON
)
{
struct
sk_buff
*
beacon
=
ieee80211_beacon_get
(
hw
,
vif
);
...
...
@@ -2431,8 +2443,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
iwl_mac_beacon_update
(
hw
,
beacon
);
}
mutex_unlock
(
&
priv
->
mutex
);
if
(
changes
&
BSS_CHANGED_ERP_PREAMBLE
)
{
IWL_DEBUG_MAC80211
(
priv
,
"ERP_PREAMBLE %d
\n
"
,
bss_conf
->
use_short_preamble
);
...
...
@@ -2450,6 +2460,23 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
priv
->
staging_rxon
.
flags
&=
~
RXON_FLG_TGG_PROTECT_MSK
;
}
if
(
changes
&
BSS_CHANGED_BASIC_RATES
)
{
/* XXX use this information
*
* To do that, remove code from iwl_set_rate() and put something
* like this here:
*
if (A-band)
priv->staging_rxon.ofdm_basic_rates =
bss_conf->basic_rates;
else
priv->staging_rxon.ofdm_basic_rates =
bss_conf->basic_rates >> 4;
priv->staging_rxon.cck_basic_rates =
bss_conf->basic_rates & 0xF;
*/
}
if
(
changes
&
BSS_CHANGED_HT
)
{
iwl_ht_conf
(
priv
,
bss_conf
);
...
...
@@ -2459,10 +2486,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
if
(
changes
&
BSS_CHANGED_ASSOC
)
{
IWL_DEBUG_MAC80211
(
priv
,
"ASSOC %d
\n
"
,
bss_conf
->
assoc
);
/* This should never happen as this function should
* never be called from interrupt context. */
if
(
WARN_ON_ONCE
(
in_interrupt
()))
return
;
if
(
bss_conf
->
assoc
)
{
priv
->
assoc_id
=
bss_conf
->
aid
;
priv
->
beacon_int
=
bss_conf
->
beacon_int
;
...
...
@@ -2470,27 +2493,35 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
priv
->
timestamp
=
bss_conf
->
timestamp
;
priv
->
assoc_capability
=
bss_conf
->
assoc_capability
;
/* we have just associated, don't start scan too early
* leave time for EAPOL exchange to complete
/*
* We have just associated, don't start scan too early
* leave time for EAPOL exchange to complete.
*
* XXX: do this in mac80211
*/
priv
->
next_scan_jiffies
=
jiffies
+
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC
;
mutex_lock
(
&
priv
->
mutex
);
priv
->
cfg
->
ops
->
lib
->
post_associate
(
priv
);
mutex_unlock
(
&
priv
->
mutex
);
}
else
{
if
(
!
iwl_is_rfkill
(
priv
))
priv
->
cfg
->
ops
->
lib
->
post_associate
(
priv
);
}
else
priv
->
assoc_id
=
0
;
IWL_DEBUG_MAC80211
(
priv
,
"DISASSOC %d
\n
"
,
bss_conf
->
assoc
);
}
if
(
changes
&&
iwl_is_associated
(
priv
)
&&
priv
->
assoc_id
)
{
IWL_DEBUG_MAC80211
(
priv
,
"Changes (%#x) while associated
\n
"
,
changes
);
ret
=
iwl_send_rxon_assoc
(
priv
);
if
(
!
ret
)
{
/* Sync active_rxon with latest change. */
memcpy
((
void
*
)
&
priv
->
active_rxon
,
&
priv
->
staging_rxon
,
sizeof
(
struct
iwl_rxon_cmd
));
}
}
else
if
(
changes
&&
iwl_is_associated
(
priv
)
&&
priv
->
assoc_id
)
{
IWL_DEBUG_MAC80211
(
priv
,
"Associated Changes %d
\n
"
,
changes
);
ret
=
iwl_send_rxon_assoc
(
priv
);
if
(
!
ret
)
/* Sync active_rxon with latest change. */
memcpy
((
void
*
)
&
priv
->
active_rxon
,
&
priv
->
staging_rxon
,
sizeof
(
struct
iwl_rxon_cmd
));
}
mutex_unlock
(
&
priv
->
mutex
);
IWL_DEBUG_MAC80211
(
priv
,
"leave
\n
"
);
}
EXPORT_SYMBOL
(
iwl_bss_info_changed
);
...
...
drivers/net/wireless/iwlwifi/iwl3945-base.c
View file @
a1870b9c
...
...
@@ -2498,8 +2498,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
struct
iwl3945_rxon_cmd
*
active_rxon
=
(
struct
iwl3945_rxon_cmd
*
)(
&
priv
->
active_rxon
);
memcpy
(
&
priv
->
staging_rxon
,
&
priv
->
active_rxon
,
sizeof
(
priv
->
staging_rxon
));
priv
->
staging_rxon
.
filter_flags
|=
RXON_FILTER_ASSOC_MSK
;
active_rxon
->
filter_flags
&=
~
RXON_FILTER_ASSOC_MSK
;
}
else
{
/* Initialize our rx_config data */
...
...
@@ -3147,7 +3146,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
/* we should be verifying the device is ready to be opened */
mutex_lock
(
&
priv
->
mutex
);
memset
(
&
priv
->
staging_rxon
,
0
,
sizeof
(
priv
->
staging_rxon
));
/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
* ucode filename and max sizes are card-specific. */
...
...
drivers/net/wireless/libertas/if_spi.c
View file @
a1870b9c
...
...
@@ -812,7 +812,6 @@ static void if_spi_h2c(struct if_spi_card *card,
static
void
if_spi_e2h
(
struct
if_spi_card
*
card
)
{
int
err
=
0
;
unsigned
long
flags
;
u32
cause
;
struct
lbs_private
*
priv
=
card
->
priv
;
...
...
@@ -827,10 +826,7 @@ static void if_spi_e2h(struct if_spi_card *card)
/* generate a card interrupt */
spu_write_u16
(
card
,
IF_SPI_CARD_INT_CAUSE_REG
,
IF_SPI_CIC_HOST_EVENT
);
spin_lock_irqsave
(
&
priv
->
driver_lock
,
flags
);
lbs_queue_event
(
priv
,
cause
&
0xff
);
spin_unlock_irqrestore
(
&
priv
->
driver_lock
,
flags
);
out:
if
(
err
)
lbs_pr_err
(
"%s: error %d
\n
"
,
__func__
,
err
);
...
...
@@ -875,7 +871,12 @@ static int lbs_spi_thread(void *data)
err
=
if_spi_c2h_data
(
card
);
if
(
err
)
goto
err
;
if
(
hiStatus
&
IF_SPI_HIST_CMD_DOWNLOAD_RDY
)
{
/* workaround: in PS mode, the card does not set the Command
* Download Ready bit, but it sets TX Download Ready. */
if
(
hiStatus
&
IF_SPI_HIST_CMD_DOWNLOAD_RDY
||
(
card
->
priv
->
psstate
!=
PS_STATE_FULL_POWER
&&
(
hiStatus
&
IF_SPI_HIST_TX_DOWNLOAD_RDY
)))
{
/* This means two things. First of all,
* if there was a previous command sent, the card has
* successfully received it.
...
...
drivers/platform/x86/dell-laptop.c
View file @
a1870b9c
...
...
@@ -177,7 +177,7 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
static
int
dell_rfkill_set
(
void
*
data
,
bool
blocked
)
{
struct
calling_interface_buffer
buffer
;
int
disable
=
blocked
?
0
:
1
;
int
disable
=
blocked
?
1
:
0
;
unsigned
long
radio
=
(
unsigned
long
)
data
;
memset
(
&
buffer
,
0
,
sizeof
(
struct
calling_interface_buffer
));
...
...
drivers/platform/x86/sony-laptop.c
View file @
a1870b9c
...
...
@@ -1133,8 +1133,9 @@ static void sony_nc_rfkill_update()
continue
;
if
(
hwblock
)
{
if
(
rfkill_set_hw_state
(
sony_rfkill_devices
[
i
],
true
))
sony_nc_rfkill_set
((
void
*
)
i
,
true
);
if
(
rfkill_set_hw_state
(
sony_rfkill_devices
[
i
],
true
))
{
/* we already know we're blocked */
}
continue
;
}
...
...
net/mac80211/debugfs.c
View file @
a1870b9c
...
...
@@ -163,6 +163,29 @@ static const struct file_operations noack_ops = {
.
open
=
mac80211_open_file_generic
};
static
ssize_t
queues_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
ieee80211_local
*
local
=
file
->
private_data
;
unsigned
long
flags
;
char
buf
[
IEEE80211_MAX_QUEUES
*
20
];
int
q
,
res
=
0
;
spin_lock_irqsave
(
&
local
->
queue_stop_reason_lock
,
flags
);
for
(
q
=
0
;
q
<
local
->
hw
.
queues
;
q
++
)
res
+=
sprintf
(
buf
+
res
,
"%02d: %#.8lx/%d
\n
"
,
q
,
local
->
queue_stop_reasons
[
q
],
__netif_subqueue_stopped
(
local
->
mdev
,
q
));
spin_unlock_irqrestore
(
&
local
->
queue_stop_reason_lock
,
flags
);
return
simple_read_from_buffer
(
user_buf
,
count
,
ppos
,
buf
,
res
);
}
static
const
struct
file_operations
queues_ops
=
{
.
read
=
queues_read
,
.
open
=
mac80211_open_file_generic
};
/* statistics stuff */
#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
...
...
@@ -298,6 +321,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD
(
total_ps_buffered
);
DEBUGFS_ADD
(
wep_iv
);
DEBUGFS_ADD
(
tsf
);
DEBUGFS_ADD
(
queues
);
DEBUGFS_ADD_MODE
(
reset
,
0200
);
DEBUGFS_ADD
(
noack
);
...
...
@@ -350,6 +374,7 @@ void debugfs_hw_del(struct ieee80211_local *local)
DEBUGFS_DEL
(
total_ps_buffered
);
DEBUGFS_DEL
(
wep_iv
);
DEBUGFS_DEL
(
tsf
);
DEBUGFS_DEL
(
queues
);
DEBUGFS_DEL
(
reset
);
DEBUGFS_DEL
(
noack
);
...
...
net/mac80211/ieee80211_i.h
View file @
a1870b9c
...
...
@@ -783,6 +783,7 @@ struct ieee80211_local {
struct
dentry
*
total_ps_buffered
;
struct
dentry
*
wep_iv
;
struct
dentry
*
tsf
;
struct
dentry
*
queues
;
struct
dentry
*
reset
;
struct
dentry
*
noack
;
struct
dentry
*
statistics
;
...
...
@@ -1100,7 +1101,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
u32
ieee802_11_parse_elems_crc
(
u8
*
start
,
size_t
len
,
struct
ieee802_11_elems
*
elems
,
u64
filter
,
u32
crc
);
int
ieee80211_set_freq
(
struct
ieee80211_sub_if_data
*
sdata
,
int
freq
);
u32
ieee80211_mandatory_rates
(
struct
ieee80211_local
*
local
,
enum
ieee80211_band
band
);
...
...
net/mac80211/mlme.c
View file @
a1870b9c
...
...
@@ -1102,14 +1102,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
struct
sta_info
*
sta
;
u32
changed
=
0
,
config_changed
=
0
;
rcu_read_lock
();
sta
=
sta_info_get
(
local
,
ifmgd
->
bssid
);
if
(
!
sta
)
{
rcu_read_unlock
();
return
;
}
if
(
deauth
)
{
ifmgd
->
direct_probe_tries
=
0
;
ifmgd
->
auth_tries
=
0
;
...
...
@@ -1120,7 +1112,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
netif_tx_stop_all_queues
(
sdata
->
dev
);
netif_carrier_off
(
sdata
->
dev
);
ieee80211_sta_tear_down_BA_sessions
(
sta
);
rcu_read_lock
();
sta
=
sta_info_get
(
local
,
ifmgd
->
bssid
);
if
(
sta
)
ieee80211_sta_tear_down_BA_sessions
(
sta
);
rcu_read_unlock
();
bss
=
ieee80211_rx_bss_get
(
local
,
ifmgd
->
bssid
,
conf
->
channel
->
center_freq
,
...
...
@@ -1156,8 +1152,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ifmgd
->
ssid
,
ifmgd
->
ssid_len
);
}
rcu_read_unlock
();
ieee80211_set_wmm_default
(
sdata
);
ieee80211_recalc_idle
(
local
);
...
...
@@ -2223,7 +2217,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
capa_mask
,
capa_val
);
if
(
bss
)
{
ieee80211_set_freq
(
sdata
,
bss
->
cbss
.
channel
->
center_freq
);
local
->
oper_channel
=
bss
->
cbss
.
channel
;
local
->
oper_channel_type
=
NL80211_CHAN_NO_HT
;
ieee80211_hw_config
(
local
,
0
);
if
(
!
(
ifmgd
->
flags
&
IEEE80211_STA_SSID_SET
))
ieee80211_sta_set_ssid
(
sdata
,
bss
->
ssid
,
bss
->
ssid_len
);
...
...
@@ -2445,6 +2442,14 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
ieee80211_set_disassoc
(
sdata
,
true
,
true
,
WLAN_REASON_DEAUTH_LEAVING
);
if
(
ifmgd
->
ssid_len
==
0
)
{
/*
* Only allow association to be started if a valid SSID
* is configured.
*/
return
;
}
if
(
!
(
ifmgd
->
flags
&
IEEE80211_STA_EXT_SME
)
||
ifmgd
->
state
!=
IEEE80211_STA_MLME_ASSOCIATE
)
set_bit
(
IEEE80211_STA_REQ_AUTH
,
&
ifmgd
->
request
);
...
...
@@ -2476,6 +2481,10 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size
ifmgd
=
&
sdata
->
u
.
mgd
;
if
(
ifmgd
->
ssid_len
!=
len
||
memcmp
(
ifmgd
->
ssid
,
ssid
,
len
)
!=
0
)
{
if
(
ifmgd
->
state
==
IEEE80211_STA_MLME_ASSOCIATED
)
ieee80211_set_disassoc
(
sdata
,
true
,
true
,
WLAN_REASON_DEAUTH_LEAVING
);
/*
* Do not use reassociation if SSID is changed (different ESS).
*/
...
...
@@ -2500,6 +2509,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
if
(
compare_ether_addr
(
bssid
,
ifmgd
->
bssid
)
!=
0
&&
ifmgd
->
state
==
IEEE80211_STA_MLME_ASSOCIATED
)
ieee80211_set_disassoc
(
sdata
,
true
,
true
,
WLAN_REASON_DEAUTH_LEAVING
);
if
(
is_valid_ether_addr
(
bssid
))
{
memcpy
(
ifmgd
->
bssid
,
bssid
,
ETH_ALEN
);
ifmgd
->
flags
|=
IEEE80211_STA_BSSID_SET
;
...
...
net/mac80211/util.c
View file @
a1870b9c
...
...
@@ -774,31 +774,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
dev_queue_xmit
(
skb
);
}
int
ieee80211_set_freq
(
struct
ieee80211_sub_if_data
*
sdata
,
int
freqMHz
)
{
int
ret
=
-
EINVAL
;
struct
ieee80211_channel
*
chan
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
chan
=
ieee80211_get_channel
(
local
->
hw
.
wiphy
,
freqMHz
);
if
(
chan
&&
!
(
chan
->
flags
&
IEEE80211_CHAN_DISABLED
))
{
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
&&
chan
->
flags
&
IEEE80211_CHAN_NO_IBSS
)
return
ret
;
local
->
oper_channel
=
chan
;
local
->
oper_channel_type
=
NL80211_CHAN_NO_HT
;
if
(
local
->
sw_scanning
||
local
->
hw_scanning
)
ret
=
0
;
else
ret
=
ieee80211_hw_config
(
local
,
IEEE80211_CONF_CHANGE_CHANNEL
);
}
return
ret
;
}
u32
ieee80211_mandatory_rates
(
struct
ieee80211_local
*
local
,
enum
ieee80211_band
band
)
{
...
...
net/mac80211/wext.c
View file @
a1870b9c
...
...
@@ -55,6 +55,8 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
struct
iw_freq
*
freq
,
char
*
extra
)
{
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_DEV_TO_SUB_IF
(
dev
);
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_channel
*
chan
;
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
)
return
cfg80211_ibss_wext_siwfreq
(
dev
,
info
,
freq
,
extra
);
...
...
@@ -69,17 +71,38 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
IEEE80211_STA_AUTO_CHANNEL_SEL
;
return
0
;
}
else
return
ieee80211_set_freq
(
sdata
,
chan
=
ieee80211_get_channel
(
local
->
hw
.
wiphy
,
ieee80211_channel_to_frequency
(
freq
->
m
));
}
else
{
int
i
,
div
=
1000000
;
for
(
i
=
0
;
i
<
freq
->
e
;
i
++
)
div
/=
10
;
if
(
div
>
0
)
return
ieee80211_set_freq
(
sdata
,
freq
->
m
/
div
);
else
if
(
div
<=
0
)
return
-
EINVAL
;
chan
=
ieee80211_get_channel
(
local
->
hw
.
wiphy
,
freq
->
m
/
div
);
}
if
(
!
chan
)
return
-
EINVAL
;
if
(
chan
->
flags
&
IEEE80211_CHAN_DISABLED
)
return
-
EINVAL
;
/*
* no change except maybe auto -> fixed, ignore the HT
* setting so you can fix a channel you're on already
*/
if
(
local
->
oper_channel
==
chan
)
return
0
;
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_STATION
)
ieee80211_sta_req_auth
(
sdata
);
local
->
oper_channel
=
chan
;
local
->
oper_channel_type
=
NL80211_CHAN_NO_HT
;
ieee80211_hw_config
(
local
,
0
);
return
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment