Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
commit
f13352519e
|
@ -1865,7 +1865,6 @@ static int adm8211_probe(struct pci_dev *pdev,
|
|||
dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
|
||||
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
|
||||
dev->channel_change_time = 1000;
|
||||
dev->max_signal = 100; /* FIXME: find better value */
|
||||
|
||||
dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
|
||||
|
|
|
@ -2112,7 +2112,6 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
|
|||
priv->pm_period = 0;
|
||||
|
||||
/* unit us */
|
||||
priv->hw->channel_change_time = 100000;
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
|
|
@ -4039,7 +4039,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
|
||||
ar->hw->vif_data_size = sizeof(struct ath10k_vif);
|
||||
|
||||
ar->hw->channel_change_time = 5000;
|
||||
ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
|
||||
|
||||
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
|
|
|
@ -2549,7 +2549,6 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
|
|||
hw->wiphy->available_antennas_rx = 0x3;
|
||||
|
||||
hw->extra_tx_headroom = 2;
|
||||
hw->channel_change_time = 5000;
|
||||
|
||||
/*
|
||||
* Mark the device as detached to avoid processing
|
||||
|
|
|
@ -748,7 +748,6 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
|||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
|
||||
hw->queues = 4;
|
||||
hw->channel_change_time = 5000;
|
||||
hw->max_listen_interval = 1;
|
||||
|
||||
hw->vif_data_size = sizeof(struct ath9k_htc_vif);
|
||||
|
|
|
@ -946,7 +946,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
|||
|
||||
hw->queues = 4;
|
||||
hw->max_rates = 4;
|
||||
hw->channel_change_time = 5000;
|
||||
hw->max_listen_interval = 1;
|
||||
hw->max_rate_tries = 10;
|
||||
hw->sta_data_size = sizeof(struct ath_node);
|
||||
|
|
|
@ -1967,18 +1967,6 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
|
|||
return -ENOMEM;
|
||||
ar->num_channels = chans;
|
||||
|
||||
/*
|
||||
* I measured this, a bandswitch takes roughly
|
||||
* 135 ms and a frequency switch about 80.
|
||||
*
|
||||
* FIXME: measure these values again once EEPROM settings
|
||||
* are used, that will influence them!
|
||||
*/
|
||||
if (bands == 2)
|
||||
ar->hw->channel_change_time = 135 * 1000;
|
||||
else
|
||||
ar->hw->channel_change_time = 80 * 1000;
|
||||
|
||||
regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
|
||||
|
||||
/* second part of wiphy init */
|
||||
|
|
|
@ -1071,7 +1071,6 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
|
|||
hw->max_rates = 2; /* Primary rate and 1 fallback rate */
|
||||
|
||||
/* channel change time is dependent on chip and band */
|
||||
hw->channel_change_time = 7 * 1000;
|
||||
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
|
|
@ -301,7 +301,6 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
|
|||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
|
||||
|
||||
hw->channel_change_time = 1000; /* TODO: find actual value */
|
||||
hw->queues = 4;
|
||||
|
||||
priv->rts_threshold = -1;
|
||||
|
|
|
@ -1268,14 +1268,9 @@ static struct cfg80211_scan_request *
|
|||
_new_connect_scan_req(struct wiphy *wiphy, struct cfg80211_connect_params *sme)
|
||||
{
|
||||
struct cfg80211_scan_request *creq = NULL;
|
||||
int i, n_channels = 0;
|
||||
int i, n_channels = ieee80211_get_num_supported_channels(wiphy);
|
||||
enum ieee80211_band band;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (wiphy->bands[band])
|
||||
n_channels += wiphy->bands[band]->n_channels;
|
||||
}
|
||||
|
||||
creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
|
||||
n_channels * sizeof(void *),
|
||||
GFP_ATOMIC);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,6 +65,9 @@ enum hwsim_tx_control_flags {
|
|||
* kernel, uses:
|
||||
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
|
||||
* %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
|
||||
* @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters,
|
||||
* returns the radio ID (>= 0) or negative on errors
|
||||
* @HWSIM_CMD_DESTROY_RADIO: destroy a radio
|
||||
* @__HWSIM_CMD_MAX: enum limit
|
||||
*/
|
||||
enum {
|
||||
|
@ -72,6 +75,8 @@ enum {
|
|||
HWSIM_CMD_REGISTER,
|
||||
HWSIM_CMD_FRAME,
|
||||
HWSIM_CMD_TX_INFO_FRAME,
|
||||
HWSIM_CMD_CREATE_RADIO,
|
||||
HWSIM_CMD_DESTROY_RADIO,
|
||||
__HWSIM_CMD_MAX,
|
||||
};
|
||||
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
|
||||
|
@ -94,6 +99,14 @@ enum {
|
|||
space
|
||||
* @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
|
||||
* @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
|
||||
* @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO
|
||||
* command giving the number of channels supported by the new radio
|
||||
* @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO
|
||||
* only to destroy a radio
|
||||
* @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint
|
||||
* (nla string, length 2)
|
||||
* @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute)
|
||||
* @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute)
|
||||
* @__HWSIM_ATTR_MAX: enum limit
|
||||
*/
|
||||
|
||||
|
@ -108,6 +121,11 @@ enum {
|
|||
HWSIM_ATTR_SIGNAL,
|
||||
HWSIM_ATTR_TX_INFO,
|
||||
HWSIM_ATTR_COOKIE,
|
||||
HWSIM_ATTR_CHANNELS,
|
||||
HWSIM_ATTR_RADIO_ID,
|
||||
HWSIM_ATTR_REG_HINT_ALPHA2,
|
||||
HWSIM_ATTR_REG_CUSTOM_REG,
|
||||
HWSIM_ATTR_REG_STRICT_REG,
|
||||
__HWSIM_ATTR_MAX,
|
||||
};
|
||||
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
|
||||
|
|
|
@ -5892,8 +5892,6 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
|
|||
|
||||
hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0;
|
||||
|
||||
hw->channel_change_time = 10;
|
||||
|
||||
hw->queues = MWL8K_TX_WMM_QUEUES;
|
||||
|
||||
/* Set rssi values to dBm */
|
||||
|
|
|
@ -756,7 +756,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
|||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
|
||||
dev->channel_change_time = 1000; /* TODO: find actual value */
|
||||
priv->beacon_req_id = cpu_to_le32(0);
|
||||
priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
|
||||
priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
|
||||
|
|
|
@ -353,7 +353,6 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
|
|||
|
||||
/* TODO: Correct this value for our hw */
|
||||
/* TODO: define these hard code value */
|
||||
hw->channel_change_time = 100;
|
||||
hw->max_listen_interval = 10;
|
||||
hw->max_rate_tries = 4;
|
||||
/* hw->max_rates = 1; */
|
||||
|
|
|
@ -1468,7 +1468,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
|
|||
|
||||
/* unit us */
|
||||
/* FIXME: find a proper value */
|
||||
wl->hw->channel_change_time = 10000;
|
||||
|
||||
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
|
|
|
@ -5710,7 +5710,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
|
||||
/* unit us */
|
||||
/* FIXME: find a proper value */
|
||||
wl->hw->channel_change_time = 10000;
|
||||
wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval;
|
||||
|
||||
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
|
|
|
@ -788,7 +788,6 @@ static int wb35_probe(struct usb_interface *intf,
|
|||
dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
|
||||
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
|
||||
dev->channel_change_time = 1000;
|
||||
dev->max_signal = 100;
|
||||
dev->queues = 1;
|
||||
|
||||
|
|
|
@ -1857,6 +1857,7 @@ enum ieee80211_key_len {
|
|||
WLAN_KEY_LEN_CCMP = 16,
|
||||
WLAN_KEY_LEN_TKIP = 32,
|
||||
WLAN_KEY_LEN_AES_CMAC = 16,
|
||||
WLAN_KEY_LEN_SMS4 = 32,
|
||||
};
|
||||
|
||||
#define IEEE80211_WEP_IV_LEN 4
|
||||
|
@ -1902,6 +1903,7 @@ enum ieee80211_tdls_actioncode {
|
|||
#define WLAN_EXT_CAPA5_TDLS_PROHIBITED BIT(6)
|
||||
|
||||
#define WLAN_EXT_CAPA8_OPMODE_NOTIF BIT(6)
|
||||
#define WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED BIT(7)
|
||||
|
||||
/* TDLS specific payload type in the LLC/SNAP header */
|
||||
#define WLAN_TDLS_SNAP_RFTYPE 0x2
|
||||
|
|
|
@ -4640,6 +4640,14 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
|
|||
*/
|
||||
void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* ieee80211_get_num_supported_channels - get number of channels device has
|
||||
* @wiphy: the wiphy
|
||||
*
|
||||
* Return: the number of channels supported by the device.
|
||||
*/
|
||||
unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
|
||||
|
||||
/* Logging, debugging and troubleshooting/diagnostic helpers. */
|
||||
|
||||
/* wiphy_printk helpers, similar to dev_printk */
|
||||
|
|
|
@ -1616,8 +1616,6 @@ enum ieee80211_hw_flags {
|
|||
* @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
|
||||
* Can be used by drivers to add extra IEs.
|
||||
*
|
||||
* @channel_change_time: time (in microseconds) it takes to change channels.
|
||||
*
|
||||
* @max_signal: Maximum value for signal (rssi) in RX information, used
|
||||
* only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
|
||||
*
|
||||
|
@ -1699,7 +1697,6 @@ struct ieee80211_hw {
|
|||
u32 flags;
|
||||
unsigned int extra_tx_headroom;
|
||||
unsigned int extra_beacon_tailroom;
|
||||
int channel_change_time;
|
||||
int vif_data_size;
|
||||
int sta_data_size;
|
||||
int chanctx_data_size;
|
||||
|
@ -2122,6 +2119,11 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|||
* appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP)
|
||||
* and also take care of the EOSP and MORE_DATA bits in the frame.
|
||||
* The driver may also use ieee80211_sta_eosp() in this case.
|
||||
*
|
||||
* Note that if the driver ever buffers frames other than QoS-data
|
||||
* frames, it must take care to never send a non-QoS-data frame as
|
||||
* the last frame in a service period, adding a QoS-nulldata frame
|
||||
* after a non-QoS-data frame if needed.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -1035,6 +1035,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
ieee80211_recalc_dtim(local, sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
netif_carrier_on(dev);
|
||||
|
@ -3854,7 +3855,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy,
|
|||
new_qos_map = NULL;
|
||||
}
|
||||
|
||||
old_qos_map = rtnl_dereference(sdata->qos_map);
|
||||
old_qos_map = sdata_dereference(sdata->qos_map, sdata);
|
||||
rcu_assign_pointer(sdata->qos_map, new_qos_map);
|
||||
if (old_qos_map)
|
||||
kfree_rcu(old_qos_map, rcu_head);
|
||||
|
|
|
@ -133,7 +133,15 @@ static ssize_t ieee80211_if_fmt_##name( \
|
|||
jiffies_to_msecs(sdata->field)); \
|
||||
}
|
||||
|
||||
#define __IEEE80211_IF_FILE(name, _write) \
|
||||
#define _IEEE80211_IF_FILE_OPS(name, _read, _write) \
|
||||
static const struct file_operations name##_ops = { \
|
||||
.read = (_read), \
|
||||
.write = (_write), \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
}
|
||||
|
||||
#define _IEEE80211_IF_FILE_R_FN(name) \
|
||||
static ssize_t ieee80211_if_read_##name(struct file *file, \
|
||||
char __user *userbuf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
|
@ -141,28 +149,34 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \
|
|||
return ieee80211_if_read(file->private_data, \
|
||||
userbuf, count, ppos, \
|
||||
ieee80211_if_fmt_##name); \
|
||||
} \
|
||||
static const struct file_operations name##_ops = { \
|
||||
.read = ieee80211_if_read_##name, \
|
||||
.write = (_write), \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
}
|
||||
|
||||
#define __IEEE80211_IF_FILE_W(name) \
|
||||
#define _IEEE80211_IF_FILE_W_FN(name) \
|
||||
static ssize_t ieee80211_if_write_##name(struct file *file, \
|
||||
const char __user *userbuf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
return ieee80211_if_write(file->private_data, userbuf, count, \
|
||||
ppos, ieee80211_if_parse_##name); \
|
||||
} \
|
||||
__IEEE80211_IF_FILE(name, ieee80211_if_write_##name)
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FILE_R(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name) \
|
||||
_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL)
|
||||
|
||||
#define IEEE80211_IF_FILE_W(name) \
|
||||
_IEEE80211_IF_FILE_W_FN(name) \
|
||||
_IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name)
|
||||
|
||||
#define IEEE80211_IF_FILE_RW(name) \
|
||||
_IEEE80211_IF_FILE_R_FN(name) \
|
||||
_IEEE80211_IF_FILE_W_FN(name) \
|
||||
_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, \
|
||||
ieee80211_if_write_##name)
|
||||
|
||||
#define IEEE80211_IF_FILE(name, field, format) \
|
||||
IEEE80211_IF_FMT_##format(name, field) \
|
||||
__IEEE80211_IF_FILE(name, NULL)
|
||||
IEEE80211_IF_FMT_##format(name, field) \
|
||||
IEEE80211_IF_FILE_R(name)
|
||||
|
||||
/* common attributes */
|
||||
IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
|
||||
|
@ -199,7 +213,7 @@ ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
return len;
|
||||
}
|
||||
__IEEE80211_IF_FILE(hw_queues, NULL);
|
||||
IEEE80211_IF_FILE_R(hw_queues);
|
||||
|
||||
/* STA attributes */
|
||||
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
||||
|
@ -275,14 +289,7 @@ static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
__IEEE80211_IF_FILE_W(smps);
|
||||
|
||||
static ssize_t ieee80211_if_fmt_tkip_mic_test(
|
||||
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
IEEE80211_IF_FILE_RW(smps);
|
||||
|
||||
static ssize_t ieee80211_if_parse_tkip_mic_test(
|
||||
struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
|
||||
|
@ -349,8 +356,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
|
|||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
__IEEE80211_IF_FILE_W(tkip_mic_test);
|
||||
IEEE80211_IF_FILE_W(tkip_mic_test);
|
||||
|
||||
static ssize_t ieee80211_if_fmt_uapsd_queues(
|
||||
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
|
||||
|
@ -378,7 +384,7 @@ static ssize_t ieee80211_if_parse_uapsd_queues(
|
|||
|
||||
return buflen;
|
||||
}
|
||||
__IEEE80211_IF_FILE_W(uapsd_queues);
|
||||
IEEE80211_IF_FILE_RW(uapsd_queues);
|
||||
|
||||
static ssize_t ieee80211_if_fmt_uapsd_max_sp_len(
|
||||
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
|
||||
|
@ -406,7 +412,7 @@ static ssize_t ieee80211_if_parse_uapsd_max_sp_len(
|
|||
|
||||
return buflen;
|
||||
}
|
||||
__IEEE80211_IF_FILE_W(uapsd_max_sp_len);
|
||||
IEEE80211_IF_FILE_RW(uapsd_max_sp_len);
|
||||
|
||||
/* AP attributes */
|
||||
IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
|
||||
|
@ -419,7 +425,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
|
|||
return scnprintf(buf, buflen, "%u\n",
|
||||
skb_queue_len(&sdata->u.ap.ps.bc_buf));
|
||||
}
|
||||
__IEEE80211_IF_FILE(num_buffered_multicast, NULL);
|
||||
IEEE80211_IF_FILE_R(num_buffered_multicast);
|
||||
|
||||
/* IBSS attributes */
|
||||
static ssize_t ieee80211_if_fmt_tsf(
|
||||
|
@ -468,9 +474,10 @@ static ssize_t ieee80211_if_parse_tsf(
|
|||
}
|
||||
}
|
||||
|
||||
ieee80211_recalc_dtim(local, sdata);
|
||||
return buflen;
|
||||
}
|
||||
__IEEE80211_IF_FILE_W(tsf);
|
||||
IEEE80211_IF_FILE_RW(tsf);
|
||||
|
||||
|
||||
/* WDS attributes */
|
||||
|
|
|
@ -479,10 +479,9 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
|
|||
vif->type != NL80211_IFTYPE_AP))
|
||||
return;
|
||||
|
||||
if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
if (sdata->u.mgd.driver_smps_mode == smps_mode)
|
||||
return;
|
||||
sdata->u.mgd.driver_smps_mode = smps_mode;
|
||||
|
|
|
@ -1800,6 +1800,8 @@ ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
|
|||
int ieee80211_cs_headroom(struct ieee80211_local *local,
|
||||
struct cfg80211_crypto_settings *crypto,
|
||||
enum nl80211_iftype iftype);
|
||||
void ieee80211_recalc_dtim(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
#ifdef CONFIG_MAC80211_NOINLINE
|
||||
#define debug_noinline noinline
|
||||
|
|
|
@ -846,17 +846,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
/* TODO: consider VHT for RX chains, hopefully it's the same */
|
||||
}
|
||||
|
||||
local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
|
||||
sizeof(void *) * channels, GFP_KERNEL);
|
||||
if (!local->int_scan_req)
|
||||
return -ENOMEM;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!local->hw.wiphy->bands[band])
|
||||
continue;
|
||||
local->int_scan_req->rates[band] = (u32) -1;
|
||||
}
|
||||
|
||||
/* if low-level driver supports AP, we also support VLAN */
|
||||
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
|
||||
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
||||
|
@ -880,6 +869,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
|
||||
sizeof(void *) * channels, GFP_KERNEL);
|
||||
if (!local->int_scan_req)
|
||||
return -ENOMEM;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!local->hw.wiphy->bands[band])
|
||||
continue;
|
||||
local->int_scan_req->rates[band] = (u32) -1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MAC80211_MESH
|
||||
/* mesh depends on Kconfig, but drivers should set it if they want */
|
||||
local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
|
|
|
@ -807,6 +807,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ieee80211_recalc_dtim(local, sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
netif_carrier_on(sdata->dev);
|
||||
|
|
|
@ -437,6 +437,7 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
|
|||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_WME);
|
||||
sta->sta.wme = true;
|
||||
|
||||
return sta;
|
||||
}
|
||||
|
|
|
@ -3076,8 +3076,8 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
|||
|
||||
/* main receive path */
|
||||
|
||||
static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
||||
struct ieee80211_hdr *hdr)
|
||||
static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct sk_buff *skb = rx->skb;
|
||||
|
@ -3088,29 +3088,29 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (!bssid && !sdata->u.mgd.use_4addr)
|
||||
return 0;
|
||||
return false;
|
||||
if (!multicast &&
|
||||
!ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
|
||||
if (!(sdata->dev->flags & IFF_PROMISC) ||
|
||||
sdata->u.mgd.use_4addr)
|
||||
return 0;
|
||||
return false;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (!bssid)
|
||||
return 0;
|
||||
return false;
|
||||
if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
|
||||
ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
|
||||
return 0;
|
||||
return false;
|
||||
if (ieee80211_is_beacon(hdr->frame_control)) {
|
||||
return 1;
|
||||
return true;
|
||||
} else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
|
||||
return 0;
|
||||
return false;
|
||||
} else if (!multicast &&
|
||||
!ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
|
||||
if (!(sdata->dev->flags & IFF_PROMISC))
|
||||
return 0;
|
||||
return false;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
} else if (!rx->sta) {
|
||||
int rate_idx;
|
||||
|
@ -3126,7 +3126,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
if (!multicast &&
|
||||
!ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
|
||||
if (!(sdata->dev->flags & IFF_PROMISC))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
}
|
||||
|
@ -3135,7 +3135,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
case NL80211_IFTYPE_AP:
|
||||
if (!bssid) {
|
||||
if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
|
||||
return 0;
|
||||
return false;
|
||||
} else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
|
||||
/*
|
||||
* Accept public action frames even when the
|
||||
|
@ -3145,26 +3145,26 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
*/
|
||||
if (!multicast &&
|
||||
!ether_addr_equal(sdata->vif.addr, hdr->addr1))
|
||||
return 0;
|
||||
return false;
|
||||
if (ieee80211_is_public_action(hdr, skb->len))
|
||||
return 1;
|
||||
return true;
|
||||
if (!ieee80211_is_beacon(hdr->frame_control))
|
||||
return 0;
|
||||
return false;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_WDS:
|
||||
if (bssid || !ieee80211_is_data(hdr->frame_control))
|
||||
return 0;
|
||||
return false;
|
||||
if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (!ieee80211_is_public_action(hdr, skb->len) &&
|
||||
!ieee80211_is_probe_req(hdr->frame_control) &&
|
||||
!ieee80211_is_probe_resp(hdr->frame_control) &&
|
||||
!ieee80211_is_beacon(hdr->frame_control))
|
||||
return 0;
|
||||
return false;
|
||||
if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
|
||||
!multicast)
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
|
@ -3175,7 +3175,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3191,13 +3191,11 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
|||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
int prepares;
|
||||
|
||||
rx->skb = skb;
|
||||
status->rx_flags |= IEEE80211_RX_RA_MATCH;
|
||||
prepares = prepare_for_handlers(rx, hdr);
|
||||
|
||||
if (!prepares)
|
||||
if (!prepare_for_handlers(rx, hdr))
|
||||
return false;
|
||||
|
||||
if (!consume) {
|
||||
|
|
|
@ -300,6 +300,35 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
if (!sta)
|
||||
return NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
tx_latency = rcu_dereference(local->tx_latency);
|
||||
/* init stations Tx latency statistics && TID bins */
|
||||
if (tx_latency) {
|
||||
sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS *
|
||||
sizeof(struct ieee80211_tx_latency_stat),
|
||||
GFP_ATOMIC);
|
||||
if (!sta->tx_lat) {
|
||||
rcu_read_unlock();
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (tx_latency->n_ranges) {
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||
/* size of bins is size of the ranges +1 */
|
||||
sta->tx_lat[i].bin_count =
|
||||
tx_latency->n_ranges + 1;
|
||||
sta->tx_lat[i].bins =
|
||||
kcalloc(sta->tx_lat[i].bin_count,
|
||||
sizeof(u32), GFP_ATOMIC);
|
||||
if (!sta->tx_lat[i].bins) {
|
||||
rcu_read_unlock();
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
spin_lock_init(&sta->lock);
|
||||
INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
|
||||
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
|
||||
|
@ -324,10 +353,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
|
||||
ewma_init(&sta->chain_signal_avg[i], 1024, 8);
|
||||
|
||||
if (sta_prepare_rate_control(local, sta, gfp)) {
|
||||
kfree(sta);
|
||||
return NULL;
|
||||
}
|
||||
if (sta_prepare_rate_control(local, sta, gfp))
|
||||
goto free;
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||
/*
|
||||
|
@ -371,34 +398,17 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
tx_latency = rcu_dereference(local->tx_latency);
|
||||
/* init stations Tx latency statistics && TID bins */
|
||||
if (tx_latency)
|
||||
sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS *
|
||||
sizeof(struct ieee80211_tx_latency_stat),
|
||||
GFP_ATOMIC);
|
||||
|
||||
/*
|
||||
* if Tx latency and bins are enabled and the previous allocation
|
||||
* succeeded
|
||||
*/
|
||||
if (tx_latency && tx_latency->n_ranges && sta->tx_lat)
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||
/* size of bins is size of the ranges +1 */
|
||||
sta->tx_lat[i].bin_count =
|
||||
tx_latency->n_ranges + 1;
|
||||
sta->tx_lat[i].bins = kcalloc(sta->tx_lat[i].bin_count,
|
||||
sizeof(u32),
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
|
||||
|
||||
return sta;
|
||||
|
||||
free:
|
||||
if (sta->tx_lat) {
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
|
||||
kfree(sta->tx_lat[i].bins);
|
||||
kfree(sta->tx_lat);
|
||||
}
|
||||
kfree(sta);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sta_info_insert_check(struct sta_info *sta)
|
||||
|
@ -1143,7 +1153,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
|||
|
||||
static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, int tid,
|
||||
enum ieee80211_frame_release_type reason)
|
||||
enum ieee80211_frame_release_type reason,
|
||||
bool call_driver)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_qos_hdr *nullfunc;
|
||||
|
@ -1201,7 +1212,9 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
|
|||
IEEE80211_TX_STATUS_EOSP |
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
|
||||
drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false);
|
||||
if (call_driver)
|
||||
drv_allow_buffered_frames(local, sta, BIT(tid), 1,
|
||||
reason, false);
|
||||
|
||||
skb->dev = sdata->dev;
|
||||
|
||||
|
@ -1217,6 +1230,17 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int find_highest_prio_tid(unsigned long tids)
|
||||
{
|
||||
/* lower 3 TIDs aren't ordered perfectly */
|
||||
if (tids & 0xF8)
|
||||
return fls(tids) - 1;
|
||||
/* TID 0 is BE just like TID 3 */
|
||||
if (tids & BIT(0))
|
||||
return 0;
|
||||
return fls(tids) - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
||||
int n_frames, u8 ignored_acs,
|
||||
|
@ -1224,7 +1248,6 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
bool found = false;
|
||||
bool more_data = false;
|
||||
int ac;
|
||||
unsigned long driver_release_tids = 0;
|
||||
|
@ -1235,9 +1258,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
|
||||
__skb_queue_head_init(&frames);
|
||||
|
||||
/*
|
||||
* Get response frame(s) and more data bit for it.
|
||||
*/
|
||||
/* Get response frame(s) and more data bit for the last one. */
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
unsigned long tids;
|
||||
|
||||
|
@ -1246,43 +1267,48 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
|
||||
tids = ieee80211_tids_for_ac(ac);
|
||||
|
||||
if (!found) {
|
||||
driver_release_tids = sta->driver_buffered_tids & tids;
|
||||
if (driver_release_tids) {
|
||||
found = true;
|
||||
} else {
|
||||
struct sk_buff *skb;
|
||||
/* if we already have frames from software, then we can't also
|
||||
* release from hardware queues
|
||||
*/
|
||||
if (skb_queue_empty(&frames))
|
||||
driver_release_tids |= sta->driver_buffered_tids & tids;
|
||||
|
||||
while (n_frames > 0) {
|
||||
skb = skb_dequeue(&sta->tx_filtered[ac]);
|
||||
if (!skb) {
|
||||
skb = skb_dequeue(
|
||||
&sta->ps_tx_buf[ac]);
|
||||
if (skb)
|
||||
local->total_ps_buffered--;
|
||||
}
|
||||
if (!skb)
|
||||
break;
|
||||
n_frames--;
|
||||
found = true;
|
||||
__skb_queue_tail(&frames, skb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the driver has data on more than one TID then
|
||||
if (driver_release_tids) {
|
||||
/* If the driver has data on more than one TID then
|
||||
* certainly there's more data if we release just a
|
||||
* single frame now (from a single TID).
|
||||
* single frame now (from a single TID). This will
|
||||
* only happen for PS-Poll.
|
||||
*/
|
||||
if (reason == IEEE80211_FRAME_RELEASE_PSPOLL &&
|
||||
hweight16(driver_release_tids) > 1) {
|
||||
more_data = true;
|
||||
driver_release_tids =
|
||||
BIT(ffs(driver_release_tids) - 1);
|
||||
BIT(find_highest_prio_tid(
|
||||
driver_release_tids));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
struct sk_buff *skb;
|
||||
|
||||
while (n_frames > 0) {
|
||||
skb = skb_dequeue(&sta->tx_filtered[ac]);
|
||||
if (!skb) {
|
||||
skb = skb_dequeue(
|
||||
&sta->ps_tx_buf[ac]);
|
||||
if (skb)
|
||||
local->total_ps_buffered--;
|
||||
}
|
||||
if (!skb)
|
||||
break;
|
||||
n_frames--;
|
||||
__skb_queue_tail(&frames, skb);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have more frames buffered on this AC, then set the
|
||||
* more-data bit and abort the loop since we can't send more
|
||||
* data from other ACs before the buffered frames from this.
|
||||
*/
|
||||
if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
|
||||
!skb_queue_empty(&sta->ps_tx_buf[ac])) {
|
||||
more_data = true;
|
||||
|
@ -1290,7 +1316,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (skb_queue_empty(&frames) && !driver_release_tids) {
|
||||
int tid;
|
||||
|
||||
/*
|
||||
|
@ -1311,15 +1337,13 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
/* This will evaluate to 1, 3, 5 or 7. */
|
||||
tid = 7 - ((ffs(~ignored_acs) - 1) << 1);
|
||||
|
||||
ieee80211_send_null_response(sdata, sta, tid, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!driver_release_tids) {
|
||||
ieee80211_send_null_response(sdata, sta, tid, reason, true);
|
||||
} else if (!driver_release_tids) {
|
||||
struct sk_buff_head pending;
|
||||
struct sk_buff *skb;
|
||||
int num = 0;
|
||||
u16 tids = 0;
|
||||
bool need_null = false;
|
||||
|
||||
skb_queue_head_init(&pending);
|
||||
|
||||
|
@ -1353,22 +1377,57 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
ieee80211_is_qos_nullfunc(hdr->frame_control))
|
||||
qoshdr = ieee80211_get_qos_ctl(hdr);
|
||||
|
||||
/* end service period after last frame */
|
||||
if (skb_queue_empty(&frames)) {
|
||||
if (reason == IEEE80211_FRAME_RELEASE_UAPSD &&
|
||||
qoshdr)
|
||||
*qoshdr |= IEEE80211_QOS_CTL_EOSP;
|
||||
tids |= BIT(skb->priority);
|
||||
|
||||
__skb_queue_tail(&pending, skb);
|
||||
|
||||
/* end service period after last frame or add one */
|
||||
if (!skb_queue_empty(&frames))
|
||||
continue;
|
||||
|
||||
if (reason != IEEE80211_FRAME_RELEASE_UAPSD) {
|
||||
/* for PS-Poll, there's only one frame */
|
||||
info->flags |= IEEE80211_TX_STATUS_EOSP |
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* For uAPSD, things are a bit more complicated. If the
|
||||
* last frame has a QoS header (i.e. is a QoS-data or
|
||||
* QoS-nulldata frame) then just set the EOSP bit there
|
||||
* and be done.
|
||||
* If the frame doesn't have a QoS header (which means
|
||||
* it should be a bufferable MMPDU) then we can't set
|
||||
* the EOSP bit in the QoS header; add a QoS-nulldata
|
||||
* frame to the list to send it after the MMPDU.
|
||||
*
|
||||
* Note that this code is only in the mac80211-release
|
||||
* code path, we assume that the driver will not buffer
|
||||
* anything but QoS-data frames, or if it does, will
|
||||
* create the QoS-nulldata frame by itself if needed.
|
||||
*
|
||||
* Cf. 802.11-2012 10.2.1.10 (c).
|
||||
*/
|
||||
if (qoshdr) {
|
||||
*qoshdr |= IEEE80211_QOS_CTL_EOSP;
|
||||
|
||||
info->flags |= IEEE80211_TX_STATUS_EOSP |
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
} else {
|
||||
/* The standard isn't completely clear on this
|
||||
* as it says the more-data bit should be set
|
||||
* if there are more BUs. The QoS-Null frame
|
||||
* we're about to send isn't buffered yet, we
|
||||
* only create it below, but let's pretend it
|
||||
* was buffered just in case some clients only
|
||||
* expect more-data=0 when eosp=1.
|
||||
*/
|
||||
hdr->frame_control |=
|
||||
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
need_null = true;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (qoshdr)
|
||||
tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK);
|
||||
else
|
||||
tids |= BIT(0);
|
||||
|
||||
__skb_queue_tail(&pending, skb);
|
||||
break;
|
||||
}
|
||||
|
||||
drv_allow_buffered_frames(local, sta, tids, num,
|
||||
|
@ -1376,17 +1435,22 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
|
||||
ieee80211_add_pending_skbs(local, &pending);
|
||||
|
||||
if (need_null)
|
||||
ieee80211_send_null_response(
|
||||
sdata, sta, find_highest_prio_tid(tids),
|
||||
reason, false);
|
||||
|
||||
sta_info_recalc_tim(sta);
|
||||
} else {
|
||||
/*
|
||||
* We need to release a frame that is buffered somewhere in the
|
||||
* driver ... it'll have to handle that.
|
||||
* Note that, as per the comment above, it'll also have to see
|
||||
* if there is more than just one frame on the specific TID that
|
||||
* we're releasing from, and it needs to set the more-data bit
|
||||
* accordingly if we tell it that there's no more data. If we do
|
||||
* tell it there's more data, then of course the more-data bit
|
||||
* needs to be set anyway.
|
||||
* Note that the driver also has to check the number of frames
|
||||
* on the TIDs we're releasing from - if there are more than
|
||||
* n_frames it has to set the more-data bit (if we didn't ask
|
||||
* it to set it anyway due to other buffered frames); if there
|
||||
* are fewer than n_frames it has to make sure to adjust that
|
||||
* to allow the service period to end properly.
|
||||
*/
|
||||
drv_release_buffered_frames(local, sta, driver_release_tids,
|
||||
n_frames, reason, more_data);
|
||||
|
@ -1394,9 +1458,9 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
/*
|
||||
* Note that we don't recalculate the TIM bit here as it would
|
||||
* most likely have no effect at all unless the driver told us
|
||||
* that the TID became empty before returning here from the
|
||||
* that the TID(s) became empty before returning here from the
|
||||
* release function.
|
||||
* Either way, however, when the driver tells us that the TID
|
||||
* Either way, however, when the driver tells us that the TID(s)
|
||||
* became empty we'll do the TIM recalculation.
|
||||
*/
|
||||
}
|
||||
|
@ -1485,6 +1549,8 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
|
|||
if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
|
||||
return;
|
||||
|
||||
trace_api_sta_set_buffered(sta->local, pubsta, tid, buffered);
|
||||
|
||||
if (buffered)
|
||||
set_bit(tid, &sta->driver_buffered_tids);
|
||||
else
|
||||
|
|
|
@ -1835,6 +1835,33 @@ TRACE_EVENT(api_eosp,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(api_sta_set_buffered,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sta *sta,
|
||||
u8 tid, bool buffered),
|
||||
|
||||
TP_ARGS(local, sta, tid, buffered),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
STA_ENTRY
|
||||
__field(u8, tid)
|
||||
__field(bool, buffered)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
STA_ASSIGN;
|
||||
__entry->tid = tid;
|
||||
__entry->buffered = buffered;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT STA_PR_FMT " tid:%d buffered:%d",
|
||||
LOCAL_PR_ARG, STA_PR_ARG, __entry->tid, __entry->buffered
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
* Tracing for internal functions
|
||||
* (which may also be called in response to driver calls)
|
||||
|
|
|
@ -500,6 +500,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
|||
info->control.jiffies = jiffies;
|
||||
info->control.vif = &tx->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
|
||||
|
||||
if (!timer_pending(&local->sta_cleanup))
|
||||
|
@ -1073,6 +1074,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
|
|||
queued = true;
|
||||
info->control.vif = &tx->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
__skb_queue_tail(&tid_tx->pending, skb);
|
||||
if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
|
||||
purge_skb = __skb_dequeue(&tid_tx->pending);
|
||||
|
|
|
@ -2734,3 +2734,44 @@ int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_parse_p2p_noa);
|
||||
|
||||
void ieee80211_recalc_dtim(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
u64 tsf = drv_get_tsf(local, sdata);
|
||||
u64 dtim_count = 0;
|
||||
u16 beacon_int = sdata->vif.bss_conf.beacon_int * 1024;
|
||||
u8 dtim_period = sdata->vif.bss_conf.dtim_period;
|
||||
struct ps_data *ps;
|
||||
u8 bcns_from_dtim;
|
||||
|
||||
if (tsf == -1ULL || !beacon_int || !dtim_period)
|
||||
return;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
||||
if (!sdata->bss)
|
||||
return;
|
||||
|
||||
ps = &sdata->bss->ps;
|
||||
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
ps = &sdata->u.mesh.ps;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* actually finds last dtim_count, mac80211 will update in
|
||||
* __beacon_add_tim().
|
||||
* dtim_count = dtim_period - (tsf / bcn_int) % dtim_period
|
||||
*/
|
||||
do_div(tsf, beacon_int);
|
||||
bcns_from_dtim = do_div(tsf, dtim_period);
|
||||
/* just had a DTIM */
|
||||
if (!bcns_from_dtim)
|
||||
dtim_count = 0;
|
||||
else
|
||||
dtim_count = dtim_period - bcns_from_dtim;
|
||||
|
||||
ps->dtim_count = dtim_count;
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
|
|||
* APs with pairwise keys should never receive Michael MIC
|
||||
* errors for non-zero keyidx because these are reserved for
|
||||
* group keys and only the AP is sending real multicast
|
||||
* frames in the BSS. (
|
||||
* frames in the BSS.
|
||||
*/
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
|
|
|
@ -5285,12 +5285,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
goto unlock;
|
||||
}
|
||||
} else {
|
||||
enum ieee80211_band band;
|
||||
n_channels = 0;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||
if (wiphy->bands[band])
|
||||
n_channels += wiphy->bands[band]->n_channels;
|
||||
n_channels = ieee80211_get_num_supported_channels(wiphy);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
|
||||
|
@ -5498,11 +5493,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
if (!n_channels)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
n_channels = 0;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||
if (wiphy->bands[band])
|
||||
n_channels += wiphy->bands[band]->n_channels;
|
||||
n_channels = ieee80211_get_num_supported_channels(wiphy);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
|
||||
|
@ -6795,6 +6786,55 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
|
||||
enum nl80211_commands cmd,
|
||||
enum nl80211_attrs attr,
|
||||
int vendor_event_idx,
|
||||
int approxlen, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
const struct nl80211_vendor_cmd_info *info;
|
||||
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_TESTMODE:
|
||||
if (WARN_ON(vendor_event_idx != -1))
|
||||
return NULL;
|
||||
info = NULL;
|
||||
break;
|
||||
case NL80211_CMD_VENDOR:
|
||||
if (WARN_ON(vendor_event_idx < 0 ||
|
||||
vendor_event_idx >= wiphy->n_vendor_events))
|
||||
return NULL;
|
||||
info = &wiphy->vendor_events[vendor_event_idx];
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0,
|
||||
cmd, attr, info, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
|
||||
|
||||
void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
|
||||
void *hdr = ((void **)skb->cb)[1];
|
||||
struct nlattr *data = ((void **)skb->cb)[2];
|
||||
enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
|
||||
|
||||
nla_nest_end(skb, data);
|
||||
genlmsg_end(skb, hdr);
|
||||
|
||||
if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
|
||||
mcgrp = NL80211_MCGRP_VENDOR;
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
|
||||
mcgrp, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_send_event_skb);
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
|
@ -6921,55 +6961,6 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
|
||||
enum nl80211_commands cmd,
|
||||
enum nl80211_attrs attr,
|
||||
int vendor_event_idx,
|
||||
int approxlen, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
const struct nl80211_vendor_cmd_info *info;
|
||||
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_TESTMODE:
|
||||
if (WARN_ON(vendor_event_idx != -1))
|
||||
return NULL;
|
||||
info = NULL;
|
||||
break;
|
||||
case NL80211_CMD_VENDOR:
|
||||
if (WARN_ON(vendor_event_idx < 0 ||
|
||||
vendor_event_idx >= wiphy->n_vendor_events))
|
||||
return NULL;
|
||||
info = &wiphy->vendor_events[vendor_event_idx];
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0,
|
||||
cmd, attr, info, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
|
||||
|
||||
void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
|
||||
void *hdr = ((void **)skb->cb)[1];
|
||||
struct nlattr *data = ((void **)skb->cb)[2];
|
||||
enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
|
||||
|
||||
nla_nest_end(skb, data);
|
||||
genlmsg_end(skb, hdr);
|
||||
|
||||
if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
|
||||
mcgrp = NL80211_MCGRP_VENDOR;
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
|
||||
mcgrp, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_send_event_skb);
|
||||
#endif
|
||||
|
||||
static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
||||
|
|
|
@ -1089,11 +1089,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||
/* Determine number of channels, needed to allocate creq */
|
||||
if (wreq && wreq->num_channels)
|
||||
n_channels = wreq->num_channels;
|
||||
else {
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||
if (wiphy->bands[band])
|
||||
n_channels += wiphy->bands[band]->n_channels;
|
||||
}
|
||||
else
|
||||
n_channels = ieee80211_get_num_supported_channels(wiphy);
|
||||
|
||||
creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
|
||||
n_channels * sizeof(void *),
|
||||
|
|
|
@ -70,18 +70,11 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
|
|||
if (rdev->scan_req)
|
||||
return -EBUSY;
|
||||
|
||||
if (wdev->conn->params.channel) {
|
||||
if (wdev->conn->params.channel)
|
||||
n_channels = 1;
|
||||
} else {
|
||||
enum ieee80211_band band;
|
||||
n_channels = 0;
|
||||
else
|
||||
n_channels = ieee80211_get_num_supported_channels(wdev->wiphy);
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
if (!wdev->wiphy->bands[band])
|
||||
continue;
|
||||
n_channels += wdev->wiphy->bands[band]->n_channels;
|
||||
}
|
||||
}
|
||||
request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
|
||||
sizeof(request->channels[0]) * n_channels,
|
||||
GFP_KERNEL);
|
||||
|
|
|
@ -879,7 +879,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
|||
|
||||
dev->ieee80211_ptr->use_4addr = false;
|
||||
dev->ieee80211_ptr->mesh_id_up_len = 0;
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
|
||||
switch (otype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
@ -1479,6 +1481,19 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy)
|
||||
{
|
||||
enum ieee80211_band band;
|
||||
unsigned int n_channels = 0;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||
if (wiphy->bands[band])
|
||||
n_channels += wiphy->bands[band]->n_channels;
|
||||
|
||||
return n_channels;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_num_supported_channels);
|
||||
|
||||
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
|
||||
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
||||
const unsigned char rfc1042_header[] __aligned(2) =
|
||||
|
|
|
@ -370,7 +370,7 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
|
|||
u8 oshort = wdev->wiphy->retry_short;
|
||||
int err;
|
||||
|
||||
if (retry->disabled ||
|
||||
if (retry->disabled || retry->value < 1 || retry->value > 255 ||
|
||||
(retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -412,9 +412,9 @@ int cfg80211_wext_giwretry(struct net_device *dev,
|
|||
* First return short value, iwconfig will ask long value
|
||||
* later if needed
|
||||
*/
|
||||
retry->flags |= IW_RETRY_LIMIT;
|
||||
retry->flags |= IW_RETRY_LIMIT | IW_RETRY_SHORT;
|
||||
retry->value = wdev->wiphy->retry_short;
|
||||
if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
|
||||
if (wdev->wiphy->retry_long == wdev->wiphy->retry_short)
|
||||
retry->flags |= IW_RETRY_LONG;
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue