Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits)
qlcnic: adding co maintainer
ixgbe: add support for active DA cables
ixgbe: dcb, do not tag tc_prio_control frames
ixgbe: fix ixgbe_tx_is_paused logic
ixgbe: always enable vlan strip/insert when DCB is enabled
ixgbe: remove some redundant code in setting FCoE FIP filter
ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp
ixgbe: fix header len when unsplit packet overflows to data buffer
ipv6: Never schedule DAD timer on dead address
ipv6: Use POSTDAD state
ipv6: Use state_lock to protect ifa state
ipv6: Replace inet6_ifaddr->dead with state
cxgb4: notify upper drivers if the device is already up when they load
cxgb4: keep interrupts available when the ports are brought down
cxgb4: fix initial addition of MAC address
cnic: Return SPQ credit to bnx2x after ring setup and shutdown.
cnic: Convert cnic_local_flags to atomic ops.
can: Fix SJA1000 command register writes on SMP systems
bridge: fix build for CONFIG_SYSFS disabled
ARCNET: Limit com20020 PCI ID matches for SOHARD cards
...
Fix up various conflicts with pcmcia tree drivers/net/
{pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and
wireless/orinoco/spectrum_cs.c} and feature removal
(Documentation/feature-removal-schedule.txt).
Also fix a non-content conflict due to pm_qos_requirement getting
renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/pm_qos_params.h>
|
||||
#include <net/sch_generic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
@@ -83,7 +85,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
{
|
||||
struct cfg80211_bss *cbss;
|
||||
struct ieee80211_bss *bss;
|
||||
int clen;
|
||||
int clen, srlen;
|
||||
s32 signal = 0;
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
|
||||
@@ -112,23 +114,24 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
bss->dtim_period = tim_ie->dtim_period;
|
||||
}
|
||||
|
||||
bss->supp_rates_len = 0;
|
||||
/* replace old supported rates if we get new values */
|
||||
srlen = 0;
|
||||
if (elems->supp_rates) {
|
||||
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
|
||||
clen = IEEE80211_MAX_SUPP_RATES;
|
||||
if (clen > elems->supp_rates_len)
|
||||
clen = elems->supp_rates_len;
|
||||
memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates,
|
||||
clen);
|
||||
bss->supp_rates_len += clen;
|
||||
memcpy(bss->supp_rates, elems->supp_rates, clen);
|
||||
srlen += clen;
|
||||
}
|
||||
if (elems->ext_supp_rates) {
|
||||
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
|
||||
clen = IEEE80211_MAX_SUPP_RATES - srlen;
|
||||
if (clen > elems->ext_supp_rates_len)
|
||||
clen = elems->ext_supp_rates_len;
|
||||
memcpy(&bss->supp_rates[bss->supp_rates_len],
|
||||
elems->ext_supp_rates, clen);
|
||||
bss->supp_rates_len += clen;
|
||||
memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
|
||||
srlen += clen;
|
||||
}
|
||||
if (srlen)
|
||||
bss->supp_rates_len = srlen;
|
||||
|
||||
bss->wmm_used = elems->wmm_param || elems->wmm_info;
|
||||
bss->uapsd_supported = is_uapsd_supported(elems);
|
||||
@@ -246,6 +249,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
bool was_hw_scan;
|
||||
|
||||
trace_api_scan_completed(local, aborted);
|
||||
|
||||
mutex_lock(&local->scan_mtx);
|
||||
|
||||
/*
|
||||
@@ -322,6 +327,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
|
||||
ieee80211_offchannel_stop_beaconing(local);
|
||||
|
||||
local->leave_oper_channel_time = 0;
|
||||
local->next_scan_state = SCAN_DECISION;
|
||||
local->scan_channel_idx = 0;
|
||||
|
||||
@@ -406,7 +412,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
if (local->ops->hw_scan) {
|
||||
WARN_ON(!ieee80211_prep_hw_scan(local));
|
||||
rc = drv_hw_scan(local, local->hw_scan_req);
|
||||
rc = drv_hw_scan(local, sdata, local->hw_scan_req);
|
||||
} else
|
||||
rc = ieee80211_start_sw_scan(local);
|
||||
|
||||
@@ -426,11 +432,28 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
|
||||
{
|
||||
/*
|
||||
* TODO: channel switching also consumes quite some time,
|
||||
* add that delay as well to get a better estimation
|
||||
*/
|
||||
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
return IEEE80211_PASSIVE_CHANNEL_TIME;
|
||||
return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
|
||||
}
|
||||
|
||||
static int ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
unsigned long *next_delay)
|
||||
{
|
||||
bool associated = false;
|
||||
bool tx_empty = true;
|
||||
bool bad_latency;
|
||||
bool listen_int_exceeded;
|
||||
unsigned long min_beacon_int = 0;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_channel *next_chan;
|
||||
|
||||
/* if no more bands/channels left, complete scan and advance to the idle state */
|
||||
if (local->scan_channel_idx >= local->scan_req->n_channels) {
|
||||
@@ -438,7 +461,11 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check if at least one STA interface is associated */
|
||||
/*
|
||||
* check if at least one STA interface is associated,
|
||||
* check if at least one STA interface has pending tx frames
|
||||
* and grab the lowest used beacon interval
|
||||
*/
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
@@ -447,7 +474,16 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
if (sdata->u.mgd.associated) {
|
||||
associated = true;
|
||||
break;
|
||||
|
||||
if (sdata->vif.bss_conf.beacon_int <
|
||||
min_beacon_int || min_beacon_int == 0)
|
||||
min_beacon_int =
|
||||
sdata->vif.bss_conf.beacon_int;
|
||||
|
||||
if (!qdisc_all_tx_empty(sdata->dev)) {
|
||||
tx_empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,11 +492,34 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
if (local->scan_channel) {
|
||||
/*
|
||||
* we're currently scanning a different channel, let's
|
||||
* switch back to the operating channel now if at least
|
||||
* one interface is associated. Otherwise just scan the
|
||||
* next channel
|
||||
* see if we can scan another channel without interfering
|
||||
* with the current traffic situation.
|
||||
*
|
||||
* Since we don't know if the AP has pending frames for us
|
||||
* we can only check for our tx queues and use the current
|
||||
* pm_qos requirements for rx. Hence, if no tx traffic occurs
|
||||
* at all we will scan as many channels in a row as the pm_qos
|
||||
* latency allows us to. Additionally we also check for the
|
||||
* currently negotiated listen interval to prevent losing
|
||||
* frames unnecessarily.
|
||||
*
|
||||
* Otherwise switch back to the operating channel.
|
||||
*/
|
||||
if (associated)
|
||||
next_chan = local->scan_req->channels[local->scan_channel_idx];
|
||||
|
||||
bad_latency = time_after(jiffies +
|
||||
ieee80211_scan_get_channel_time(next_chan),
|
||||
local->leave_oper_channel_time +
|
||||
usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
|
||||
|
||||
listen_int_exceeded = time_after(jiffies +
|
||||
ieee80211_scan_get_channel_time(next_chan),
|
||||
local->leave_oper_channel_time +
|
||||
usecs_to_jiffies(min_beacon_int * 1024) *
|
||||
local->hw.conf.listen_interval);
|
||||
|
||||
if (associated && ( !tx_empty || bad_latency ||
|
||||
listen_int_exceeded))
|
||||
local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
|
||||
else
|
||||
local->next_scan_state = SCAN_SET_CHANNEL;
|
||||
@@ -492,6 +551,9 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca
|
||||
else
|
||||
*next_delay = HZ / 10;
|
||||
|
||||
/* remember when we left the operating channel */
|
||||
local->leave_oper_channel_time = jiffies;
|
||||
|
||||
/* advance to the next channel to be scanned */
|
||||
local->next_scan_state = SCAN_SET_CHANNEL;
|
||||
}
|
||||
@@ -594,7 +656,7 @@ void ieee80211_scan_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (local->hw_scan_req) {
|
||||
int rc = drv_hw_scan(local, local->hw_scan_req);
|
||||
int rc = drv_hw_scan(local, sdata, local->hw_scan_req);
|
||||
mutex_unlock(&local->scan_mtx);
|
||||
if (rc)
|
||||
ieee80211_scan_completed(&local->hw, true);
|
||||
@@ -667,10 +729,12 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *ssid, u8 ssid_len)
|
||||
const u8 *ssid, u8 ssid_len,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int ret = -EBUSY;
|
||||
enum nl80211_band band;
|
||||
|
||||
mutex_lock(&local->scan_mtx);
|
||||
|
||||
@@ -678,6 +742,30 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
|
||||
if (local->scan_req)
|
||||
goto unlock;
|
||||
|
||||
/* fill internal scan request */
|
||||
if (!chan) {
|
||||
int i, nchan = 0;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!local->hw.wiphy->bands[band])
|
||||
continue;
|
||||
for (i = 0;
|
||||
i < local->hw.wiphy->bands[band]->n_channels;
|
||||
i++) {
|
||||
local->int_scan_req->channels[nchan] =
|
||||
&local->hw.wiphy->bands[band]->channels[i];
|
||||
nchan++;
|
||||
}
|
||||
}
|
||||
|
||||
local->int_scan_req->n_channels = nchan;
|
||||
} else {
|
||||
local->int_scan_req->channels[0] = chan;
|
||||
local->int_scan_req->n_channels = 1;
|
||||
}
|
||||
|
||||
local->int_scan_req->ssids = &local->scan_ssid;
|
||||
local->int_scan_req->n_ssids = 1;
|
||||
memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
|
||||
local->int_scan_req->ssids[0].ssid_len = ssid_len;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user