mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-08 23:04:35 +08:00
Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next
This commit is contained in:
commit
b510446b64
@ -437,7 +437,7 @@
|
||||
</section>
|
||||
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
|
||||
!Finclude/net/mac80211.h ieee80211_beacon_get
|
||||
!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
|
||||
!Finclude/net/mac80211.h ieee80211_sta_eosp
|
||||
!Finclude/net/mac80211.h ieee80211_frame_release_type
|
||||
!Finclude/net/mac80211.h ieee80211_sta_ps_transition
|
||||
!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
|
||||
|
@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
||||
}
|
||||
|
||||
SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
|
||||
SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
|
||||
|
||||
SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
|
||||
SSB_SPROM4_TXPID2G0_SHIFT);
|
||||
|
@ -83,8 +83,8 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||
.helper = "sd8688_helper.bin",
|
||||
.firmware = "sd8688.bin",
|
||||
.helper = "mrvl/sd8688_helper.bin",
|
||||
.firmware = "mrvl/sd8688.bin",
|
||||
.reg = &btmrvl_reg_8688,
|
||||
.sd_blksz_fw_dl = 64,
|
||||
};
|
||||
@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
||||
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8688.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
|
||||
|
@ -1091,7 +1091,7 @@ static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ar5523_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct ar5523 *ar = hw->priv;
|
||||
|
||||
|
@ -53,7 +53,7 @@ TRACE_EVENT(ath6kl_wmi_cmd,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"id %d len %d",
|
||||
"id %d len %zd",
|
||||
__entry->id, __entry->buf_len
|
||||
)
|
||||
);
|
||||
@ -76,7 +76,7 @@ TRACE_EVENT(ath6kl_wmi_event,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"id %d len %d",
|
||||
"id %d len %zd",
|
||||
__entry->id, __entry->buf_len
|
||||
)
|
||||
);
|
||||
@ -108,7 +108,7 @@ TRACE_EVENT(ath6kl_sdio,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s addr 0x%x flags 0x%x len %d\n",
|
||||
"%s addr 0x%x flags 0x%x len %zd\n",
|
||||
__entry->tx ? "tx" : "rx",
|
||||
__entry->addr,
|
||||
__entry->flags,
|
||||
@ -161,7 +161,7 @@ TRACE_EVENT(ath6kl_sdio_scat,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s addr 0x%x flags 0x%x entries %d total_len %d\n",
|
||||
"%s addr 0x%x flags 0x%x entries %d total_len %zd\n",
|
||||
__entry->tx ? "tx" : "rx",
|
||||
__entry->addr,
|
||||
__entry->flags,
|
||||
@ -186,7 +186,7 @@ TRACE_EVENT(ath6kl_sdio_irq,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"irq len %d\n", __entry->buf_len
|
||||
"irq len %zd\n", __entry->buf_len
|
||||
)
|
||||
);
|
||||
|
||||
@ -211,7 +211,7 @@ TRACE_EVENT(ath6kl_htc_rx,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"status %d endpoint %d len %d\n",
|
||||
"status %d endpoint %d len %zd\n",
|
||||
__entry->status,
|
||||
__entry->endpoint,
|
||||
__entry->buf_len
|
||||
@ -239,7 +239,7 @@ TRACE_EVENT(ath6kl_htc_tx,
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"status %d endpoint %d len %d\n",
|
||||
"status %d endpoint %d len %zd\n",
|
||||
__entry->status,
|
||||
__entry->endpoint,
|
||||
__entry->buf_len
|
||||
|
@ -1745,7 +1745,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
@ -1703,7 +1703,7 @@ found:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
unsigned int vid;
|
||||
|
@ -2780,9 +2780,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
|
||||
switch (dev->dev->bus_type) {
|
||||
#ifdef CONFIG_B43_BCMA
|
||||
case B43_BUS_BCMA:
|
||||
bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
|
||||
(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
|
||||
BCMA_CC_GPIOCTL) & ~mask) | set);
|
||||
bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, mask, set);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_B43_SSB
|
||||
@ -2807,8 +2805,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
|
||||
switch (dev->dev->bus_type) {
|
||||
#ifdef CONFIG_B43_BCMA
|
||||
case B43_BUS_BCMA:
|
||||
bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
|
||||
0);
|
||||
bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 0);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_B43_SSB
|
||||
|
@ -104,14 +104,8 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
|
||||
maxpwr = sprom->maxpwr_bg;
|
||||
lpphy->max_tx_pwr_med_band = maxpwr;
|
||||
cckpo = sprom->cck2gpo;
|
||||
/*
|
||||
* We don't read SPROM's opo as specs say. On rev8 SPROMs
|
||||
* opo == ofdm2gpo and we don't know any SSB with LP-PHY
|
||||
* and SPROM rev below 8.
|
||||
*/
|
||||
B43_WARN_ON(sprom->revision < 8);
|
||||
ofdmpo = sprom->ofdm2gpo;
|
||||
if (cckpo) {
|
||||
ofdmpo = sprom->ofdm2gpo;
|
||||
for (i = 0; i < 4; i++) {
|
||||
lpphy->tx_max_rate[i] =
|
||||
maxpwr - (ofdmpo & 0xF) * 2;
|
||||
@ -124,11 +118,11 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
|
||||
ofdmpo >>= 4;
|
||||
}
|
||||
} else {
|
||||
ofdmpo &= 0xFF;
|
||||
u8 opo = sprom->opo;
|
||||
for (i = 0; i < 4; i++)
|
||||
lpphy->tx_max_rate[i] = maxpwr;
|
||||
for (i = 4; i < 15; i++)
|
||||
lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
|
||||
lpphy->tx_max_rate[i] = maxpwr - opo;
|
||||
}
|
||||
} else { /* 5GHz */
|
||||
lpphy->tx_isolation_low_band = sprom->tri5gl;
|
||||
|
@ -724,7 +724,7 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl)
|
||||
return result;
|
||||
}
|
||||
|
||||
static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct brcms_info *wl = hw->priv;
|
||||
int ret;
|
||||
|
@ -4704,8 +4704,7 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(il_mac_change_interface);
|
||||
|
||||
void
|
||||
il_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct il_priv *il = hw->priv;
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(500);
|
||||
|
@ -1720,7 +1720,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype newtype, bool newp2p);
|
||||
void il_mac_flush(struct ieee80211_hw *hw, bool drop);
|
||||
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
|
||||
int il_alloc_txq_mem(struct il_priv *il);
|
||||
void il_free_txq_mem(struct il_priv *il);
|
||||
|
||||
|
@ -1100,7 +1100,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
|
||||
}
|
||||
|
||||
static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -964,6 +964,12 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
|
||||
newtype, vif->addr);
|
||||
hwsim_check_magic(vif);
|
||||
|
||||
/*
|
||||
* interface may change from non-AP to AP in
|
||||
* which case this needs to be set up again
|
||||
*/
|
||||
vif->cab_queue = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1389,7 +1395,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
/* Not implemented, queues only on kernel side */
|
||||
}
|
||||
|
@ -259,3 +259,22 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd, u16 cmd_action,
|
||||
struct mwifiex_11ac_vht_cfg *cfg)
|
||||
{
|
||||
struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
|
||||
|
||||
cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
|
||||
cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
|
||||
S_DS_GEN);
|
||||
vhtcfg->action = cpu_to_le16(cmd_action);
|
||||
vhtcfg->band_config = cfg->band_config;
|
||||
vhtcfg->misc_config = cfg->misc_config;
|
||||
vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
|
||||
vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
|
||||
vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,7 +20,24 @@
|
||||
#ifndef _MWIFIEX_11AC_H_
|
||||
#define _MWIFIEX_11AC_H_
|
||||
|
||||
#define VHT_CFG_2GHZ BIT(0)
|
||||
#define VHT_CFG_5GHZ BIT(1)
|
||||
|
||||
enum vht_cfg_misc_config {
|
||||
VHT_CAP_TX_OPERATION = 1,
|
||||
VHT_CAP_ASSOCIATION,
|
||||
VHT_CAP_UAP_ONLY
|
||||
};
|
||||
|
||||
#define DEFAULT_VHT_MCS_SET 0xfffa
|
||||
#define DISABLE_VHT_MCS_SET 0xffff
|
||||
|
||||
#define VHT_BW_80_160_80P80 BIT(2)
|
||||
|
||||
int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc,
|
||||
u8 **buffer);
|
||||
int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd, u16 cmd_action,
|
||||
struct mwifiex_11ac_vht_cfg *cfg);
|
||||
#endif /* _MWIFIEX_11AC_H_ */
|
||||
|
@ -1374,6 +1374,13 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
mwifiex_set_ht_params(priv, bss_cfg, params);
|
||||
|
||||
if (priv->adapter->is_hw_11ac_capable) {
|
||||
mwifiex_set_vht_params(priv, bss_cfg, params);
|
||||
mwifiex_set_vht_width(priv, params->chandef.width,
|
||||
priv->ap_11ac_enabled);
|
||||
}
|
||||
|
||||
mwifiex_set_wmm_params(priv, bss_cfg, params);
|
||||
|
||||
if (params->inactivity_timeout > 0) {
|
||||
|
@ -295,6 +295,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
||||
#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
|
||||
#define HostCmd_CMD_MGMT_FRAME_REG 0x010c
|
||||
#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
|
||||
#define HostCmd_CMD_11AC_CFG 0x0112
|
||||
|
||||
#define PROTOCOL_NO_SECURITY 0x01
|
||||
#define PROTOCOL_STATIC_WEP 0x02
|
||||
@ -1363,6 +1364,15 @@ struct host_cmd_ds_sys_config {
|
||||
u8 tlv[0];
|
||||
};
|
||||
|
||||
struct host_cmd_11ac_vht_cfg {
|
||||
__le16 action;
|
||||
u8 band_config;
|
||||
u8 misc_config;
|
||||
__le32 cap_info;
|
||||
__le32 mcs_tx_set;
|
||||
__le32 mcs_rx_set;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_tlv_akmp {
|
||||
struct host_cmd_tlv tlv;
|
||||
__le16 key_mgmt;
|
||||
@ -1620,6 +1630,7 @@ struct host_cmd_ds_command {
|
||||
struct host_cmd_ds_802_11_eeprom_access eeprom;
|
||||
struct host_cmd_ds_802_11_subsc_evt subsc_evt;
|
||||
struct host_cmd_ds_sys_config uap_sys_config;
|
||||
struct host_cmd_11ac_vht_cfg vht_cfg;
|
||||
} params;
|
||||
} __packed;
|
||||
|
||||
|
@ -272,6 +272,14 @@ struct mwifiex_ds_pm_cfg {
|
||||
} param;
|
||||
};
|
||||
|
||||
struct mwifiex_11ac_vht_cfg {
|
||||
u8 band_config;
|
||||
u8 misc_config;
|
||||
u32 cap_info;
|
||||
u32 mcs_tx_set;
|
||||
u32 mcs_rx_set;
|
||||
};
|
||||
|
||||
struct mwifiex_ds_11n_tx_cfg {
|
||||
u16 tx_htcap;
|
||||
u16 tx_htinfo;
|
||||
|
@ -913,8 +913,14 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv,
|
||||
void mwifiex_set_ht_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_vht_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params);
|
||||
void mwifiex_set_vht_width(struct mwifiex_private *priv,
|
||||
enum nl80211_chan_width width,
|
||||
bool ap_11ac_disable);
|
||||
void
|
||||
mwifiex_set_wmm_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "main.h"
|
||||
#include "wmm.h"
|
||||
#include "11n.h"
|
||||
#include "11ac.h"
|
||||
|
||||
/*
|
||||
* This function prepares command to set/get RSSI information.
|
||||
@ -1258,6 +1259,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
|
||||
cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
|
||||
S_DS_GEN);
|
||||
break;
|
||||
case HostCmd_CMD_11AC_CFG:
|
||||
ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
|
||||
break;
|
||||
case HostCmd_CMD_P2P_MODE_CFG:
|
||||
cmd_ptr->command = cpu_to_le16(cmd_no);
|
||||
cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
|
||||
|
@ -907,6 +907,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
|
||||
case HostCmd_CMD_REMAIN_ON_CHAN:
|
||||
ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
|
||||
break;
|
||||
case HostCmd_CMD_11AC_CFG:
|
||||
break;
|
||||
case HostCmd_CMD_P2P_MODE_CFG:
|
||||
ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
|
||||
break;
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "11ac.h"
|
||||
|
||||
/* This function parses security related parameters from cfg80211_ap_settings
|
||||
* and sets into FW understandable bss_config structure.
|
||||
@ -177,6 +178,60 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function updates 11ac related parameters from IE
|
||||
* and sets them into bss_config structure.
|
||||
*/
|
||||
void mwifiex_set_vht_params(struct mwifiex_private *priv,
|
||||
struct mwifiex_uap_bss_param *bss_cfg,
|
||||
struct cfg80211_ap_settings *params)
|
||||
{
|
||||
const u8 *vht_ie;
|
||||
|
||||
vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
|
||||
params->beacon.tail_len);
|
||||
if (vht_ie) {
|
||||
memcpy(&bss_cfg->vht_cap, vht_ie + 2,
|
||||
sizeof(struct ieee80211_vht_cap));
|
||||
priv->ap_11ac_enabled = 1;
|
||||
} else {
|
||||
priv->ap_11ac_enabled = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable VHT only when cfg80211_ap_settings has VHT IE.
|
||||
* Otherwise disable VHT.
|
||||
*/
|
||||
void mwifiex_set_vht_width(struct mwifiex_private *priv,
|
||||
enum nl80211_chan_width width,
|
||||
bool ap_11ac_enable)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_11ac_vht_cfg vht_cfg;
|
||||
|
||||
vht_cfg.band_config = VHT_CFG_5GHZ;
|
||||
vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
|
||||
|
||||
if (!ap_11ac_enable) {
|
||||
vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
|
||||
vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
|
||||
} else {
|
||||
vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
|
||||
vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
|
||||
}
|
||||
|
||||
vht_cfg.misc_config = VHT_CAP_UAP_ONLY;
|
||||
|
||||
if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
|
||||
vht_cfg.misc_config |= VHT_BW_80_160_80P80;
|
||||
|
||||
mwifiex_send_cmd_sync(priv, HostCmd_CMD_11AC_CFG,
|
||||
HostCmd_ACT_GEN_SET, 0, &vht_cfg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function finds supported rates IE from beacon parameter and sets
|
||||
* these rates into bss_config structure.
|
||||
*/
|
||||
|
@ -670,7 +670,7 @@ static unsigned int p54_flush_count(struct p54_common *priv)
|
||||
return total;
|
||||
}
|
||||
|
||||
static void p54_flush(struct ieee80211_hw *dev, bool drop)
|
||||
static void p54_flush(struct ieee80211_hw *dev, u32 queues, bool drop)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
unsigned int total, i;
|
||||
|
@ -1366,7 +1366,7 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
|
||||
void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
|
||||
void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
|
||||
int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
|
||||
int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
|
||||
void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
|
||||
|
@ -748,7 +748,7 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
|
||||
|
||||
void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct data_queue *queue;
|
||||
|
@ -1166,7 +1166,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
|
||||
* before switch channle or power save, or tx buffer packet
|
||||
* maybe send after offchannel or rf sleep, this may cause
|
||||
* dis-association by AP */
|
||||
static void rtl_op_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
|
@ -434,7 +434,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
(u32)hdr->addr1[2], (u32)hdr->addr1[3],
|
||||
(u32)hdr->addr1[4], (u32)hdr->addr1[5]);
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
|
||||
ieee80211_rx_irqsafe(hw, skb);
|
||||
ieee80211_rx(hw, skb);
|
||||
}
|
||||
|
||||
void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb)
|
||||
|
@ -308,6 +308,8 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _rtl_rx_work(unsigned long param);
|
||||
|
||||
static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
@ -324,6 +326,12 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
|
||||
pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n",
|
||||
rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep);
|
||||
init_usb_anchor(&rtlusb->rx_submitted);
|
||||
init_usb_anchor(&rtlusb->rx_cleanup_urbs);
|
||||
|
||||
skb_queue_head_init(&rtlusb->rx_queue);
|
||||
rtlusb->rx_work_tasklet.func = _rtl_rx_work;
|
||||
rtlusb->rx_work_tasklet.data = (unsigned long)rtlusb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -405,40 +413,30 @@ static void rtl_usb_init_sw(struct ieee80211_hw *hw)
|
||||
rtlusb->disableHWSM = true;
|
||||
}
|
||||
|
||||
#define __RADIO_TAP_SIZE_RSV 32
|
||||
|
||||
static void _rtl_rx_completed(struct urb *urb);
|
||||
|
||||
static struct sk_buff *_rtl_prep_rx_urb(struct ieee80211_hw *hw,
|
||||
struct rtl_usb *rtlusb,
|
||||
struct urb *urb,
|
||||
gfp_t gfp_mask)
|
||||
static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb,
|
||||
struct urb *urb, gfp_t gfp_mask)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
void *buf;
|
||||
|
||||
skb = __dev_alloc_skb((rtlusb->rx_max_size + __RADIO_TAP_SIZE_RSV),
|
||||
gfp_mask);
|
||||
if (!skb) {
|
||||
buf = usb_alloc_coherent(rtlusb->udev, rtlusb->rx_max_size, gfp_mask,
|
||||
&urb->transfer_dma);
|
||||
if (!buf) {
|
||||
RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
|
||||
"Failed to __dev_alloc_skb!!\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
"Failed to usb_alloc_coherent!!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* reserve some space for mac80211's radiotap */
|
||||
skb_reserve(skb, __RADIO_TAP_SIZE_RSV);
|
||||
usb_fill_bulk_urb(urb, rtlusb->udev,
|
||||
usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep),
|
||||
skb->data, min(skb_tailroom(skb),
|
||||
(int)rtlusb->rx_max_size),
|
||||
_rtl_rx_completed, skb);
|
||||
buf, rtlusb->rx_max_size, _rtl_rx_completed, rtlusb);
|
||||
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
_rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep);
|
||||
return skb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef __RADIO_TAP_SIZE_RSV
|
||||
|
||||
static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -522,22 +520,11 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
|
||||
if (unicast)
|
||||
rtlpriv->link_info.num_rx_inperiod++;
|
||||
}
|
||||
if (likely(rtl_action_proc(hw, skb, false))) {
|
||||
struct sk_buff *uskb = NULL;
|
||||
u8 *pdata;
|
||||
|
||||
uskb = dev_alloc_skb(skb->len + 128);
|
||||
if (uskb) { /* drop packet on allocation failure */
|
||||
memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
|
||||
sizeof(rx_status));
|
||||
pdata = (u8 *)skb_put(uskb, skb->len);
|
||||
memcpy(pdata, skb->data, skb->len);
|
||||
ieee80211_rx_irqsafe(hw, uskb);
|
||||
}
|
||||
if (likely(rtl_action_proc(hw, skb, false)))
|
||||
ieee80211_rx(hw, skb);
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,15 +541,70 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
while (!skb_queue_empty(&rx_queue)) {
|
||||
_skb = skb_dequeue(&rx_queue);
|
||||
_rtl_usb_rx_process_agg(hw, _skb);
|
||||
ieee80211_rx_irqsafe(hw, _skb);
|
||||
ieee80211_rx(hw, _skb);
|
||||
}
|
||||
}
|
||||
|
||||
#define __RX_SKB_MAX_QUEUED 32
|
||||
|
||||
static void _rtl_rx_work(unsigned long param)
|
||||
{
|
||||
struct rtl_usb *rtlusb = (struct rtl_usb *)param;
|
||||
struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&rtlusb->rx_queue))) {
|
||||
if (unlikely(IS_USB_STOP(rtlusb))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (likely(!rtlusb->usb_rx_segregate_hdl)) {
|
||||
_rtl_usb_rx_process_noagg(hw, skb);
|
||||
} else {
|
||||
/* TO DO */
|
||||
_rtl_rx_pre_process(hw, skb);
|
||||
pr_err("rx agg not supported\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int padding = 0;
|
||||
|
||||
/* make function no-op when possible */
|
||||
if (NET_IP_ALIGN == 0 || len < sizeof(*hdr))
|
||||
return 0;
|
||||
|
||||
/* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */
|
||||
/* TODO: deduplicate common code, define helper function instead? */
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
|
||||
padding ^= NET_IP_ALIGN;
|
||||
|
||||
/* Input might be invalid, avoid accessing memory outside
|
||||
* the buffer.
|
||||
*/
|
||||
if ((unsigned long)qc - (unsigned long)hdr < len &&
|
||||
*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
|
||||
padding ^= NET_IP_ALIGN;
|
||||
}
|
||||
|
||||
if (ieee80211_has_a4(hdr->frame_control))
|
||||
padding ^= NET_IP_ALIGN;
|
||||
|
||||
return padding;
|
||||
}
|
||||
|
||||
#define __RADIO_TAP_SIZE_RSV 32
|
||||
|
||||
static void _rtl_rx_completed(struct urb *_urb)
|
||||
{
|
||||
struct sk_buff *skb = (struct sk_buff *)_urb->context;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0];
|
||||
struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context;
|
||||
struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
int err = 0;
|
||||
@ -571,28 +613,50 @@ static void _rtl_rx_completed(struct urb *_urb)
|
||||
goto free;
|
||||
|
||||
if (likely(0 == _urb->status)) {
|
||||
/* If this code were moved to work queue, would CPU
|
||||
* utilization be improved? NOTE: We shall allocate another skb
|
||||
* and reuse the original one.
|
||||
*/
|
||||
skb_put(skb, _urb->actual_length);
|
||||
unsigned int padding;
|
||||
struct sk_buff *skb;
|
||||
unsigned int qlen;
|
||||
unsigned int size = _urb->actual_length;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
if (likely(!rtlusb->usb_rx_segregate_hdl)) {
|
||||
struct sk_buff *_skb;
|
||||
_rtl_usb_rx_process_noagg(hw, skb);
|
||||
_skb = _rtl_prep_rx_urb(hw, rtlusb, _urb, GFP_ATOMIC);
|
||||
if (IS_ERR(_skb)) {
|
||||
err = PTR_ERR(_skb);
|
||||
RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
|
||||
"Can't allocate skb for bulk IN!\n");
|
||||
return;
|
||||
}
|
||||
skb = _skb;
|
||||
} else{
|
||||
/* TO DO */
|
||||
_rtl_rx_pre_process(hw, skb);
|
||||
pr_err("rx agg not supported\n");
|
||||
if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) {
|
||||
RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
|
||||
"Too short packet from bulk IN! (len: %d)\n",
|
||||
size);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
qlen = skb_queue_len(&rtlusb->rx_queue);
|
||||
if (qlen >= __RX_SKB_MAX_QUEUED) {
|
||||
RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
|
||||
"Pending RX skbuff queue full! (qlen: %d)\n",
|
||||
qlen);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE);
|
||||
padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE);
|
||||
|
||||
skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding);
|
||||
if (!skb) {
|
||||
RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
|
||||
"Can't allocate skb for bulk IN!\n");
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
_rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep);
|
||||
|
||||
/* Make sure the payload data is 4 byte aligned. */
|
||||
skb_reserve(skb, padding);
|
||||
|
||||
/* reserve some space for mac80211's radiotap */
|
||||
skb_reserve(skb, __RADIO_TAP_SIZE_RSV);
|
||||
|
||||
memcpy(skb_put(skb, size), _urb->transfer_buffer, size);
|
||||
|
||||
skb_queue_tail(&rtlusb->rx_queue, skb);
|
||||
tasklet_schedule(&rtlusb->rx_work_tasklet);
|
||||
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
@ -608,9 +672,6 @@ static void _rtl_rx_completed(struct urb *_urb)
|
||||
}
|
||||
|
||||
resubmit:
|
||||
skb_reset_tail_pointer(skb);
|
||||
skb_trim(skb, 0);
|
||||
|
||||
usb_anchor_urb(_urb, &rtlusb->rx_submitted);
|
||||
err = usb_submit_urb(_urb, GFP_ATOMIC);
|
||||
if (unlikely(err)) {
|
||||
@ -620,13 +681,34 @@ resubmit:
|
||||
return;
|
||||
|
||||
free:
|
||||
dev_kfree_skb_irq(skb);
|
||||
/* On some architectures, usb_free_coherent must not be called from
|
||||
* hardirq context. Queue urb to cleanup list.
|
||||
*/
|
||||
usb_anchor_urb(_urb, &rtlusb->rx_cleanup_urbs);
|
||||
}
|
||||
|
||||
#undef __RADIO_TAP_SIZE_RSV
|
||||
|
||||
static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
|
||||
struct urb *urb;
|
||||
|
||||
usb_kill_anchored_urbs(&rtlusb->rx_submitted);
|
||||
|
||||
tasklet_kill(&rtlusb->rx_work_tasklet);
|
||||
skb_queue_purge(&rtlusb->rx_queue);
|
||||
|
||||
while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) {
|
||||
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
|
||||
urb->transfer_buffer, urb->transfer_dma);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
}
|
||||
|
||||
static int _rtl_usb_receive(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
int i;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
@ -645,11 +727,10 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
|
||||
if (IS_ERR(skb)) {
|
||||
err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
|
||||
"Failed to prep_rx_urb!!\n");
|
||||
err = PTR_ERR(skb);
|
||||
usb_free_urb(urb);
|
||||
goto err_out;
|
||||
}
|
||||
@ -664,6 +745,7 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw)
|
||||
|
||||
err_out:
|
||||
usb_kill_anchored_urbs(&rtlusb->rx_submitted);
|
||||
_rtl_usb_cleanup_rx(hw);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -705,7 +787,7 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw)
|
||||
SET_USB_STOP(rtlusb);
|
||||
|
||||
/* clean up rx stuff. */
|
||||
usb_kill_anchored_urbs(&rtlusb->rx_submitted);
|
||||
_rtl_usb_cleanup_rx(hw);
|
||||
|
||||
/* clean up tx stuff */
|
||||
for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
|
||||
|
@ -136,11 +136,14 @@ struct rtl_usb {
|
||||
void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *);
|
||||
|
||||
/* Rx */
|
||||
u8 in_ep_nums ;
|
||||
u8 in_ep_nums;
|
||||
u32 in_ep; /* Bulk IN endpoint number */
|
||||
u32 rx_max_size; /* Bulk IN max buffer size */
|
||||
u32 rx_urb_num; /* How many Bulk INs are submitted to host. */
|
||||
struct usb_anchor rx_submitted;
|
||||
struct usb_anchor rx_cleanup_urbs;
|
||||
struct tasklet_struct rx_work_tasklet;
|
||||
struct sk_buff_head rx_queue;
|
||||
void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *,
|
||||
struct sk_buff_head *);
|
||||
void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *);
|
||||
|
@ -186,8 +186,10 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable)
|
||||
wl->set_power(true);
|
||||
|
||||
ret = pm_runtime_get_sync(&func->dev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_sync(&func->dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_enable_func(func);
|
||||
|
@ -723,6 +723,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
|
||||
wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
|
||||
wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
|
||||
wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ;
|
||||
wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -63,6 +63,8 @@
|
||||
|
||||
#define WL12XX_NUM_MAC_ADDRESSES 2
|
||||
|
||||
#define WL12XX_RX_BA_MAX_SESSIONS 3
|
||||
|
||||
struct wl127x_rx_mem_pool_addr {
|
||||
u32 addr;
|
||||
u32 addr_extra;
|
||||
|
@ -678,6 +678,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
|
||||
wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC;
|
||||
wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC;
|
||||
wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ;
|
||||
wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -1144,6 +1145,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
|
||||
static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
|
||||
{
|
||||
u32 fuse;
|
||||
s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0;
|
||||
int ret;
|
||||
|
||||
ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
|
||||
@ -1154,8 +1156,29 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
|
||||
rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET;
|
||||
|
||||
if (rom <= 0xE)
|
||||
metal = (fuse & WL18XX_METAL_VER_MASK) >>
|
||||
WL18XX_METAL_VER_OFFSET;
|
||||
else
|
||||
metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >>
|
||||
WL18XX_NEW_METAL_VER_OFFSET;
|
||||
|
||||
ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET;
|
||||
if (rdl_ver > RDL_MAX)
|
||||
rdl_ver = RDL_NONE;
|
||||
|
||||
wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)",
|
||||
rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom);
|
||||
|
||||
if (ver)
|
||||
*ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
|
||||
*ver = pg_ver;
|
||||
|
||||
ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
|
||||
|
||||
|
@ -131,6 +131,16 @@
|
||||
#define WL18XX_REG_FUSE_DATA_1_3 0xA0260C
|
||||
#define WL18XX_PG_VER_MASK 0x70
|
||||
#define WL18XX_PG_VER_OFFSET 4
|
||||
#define WL18XX_ROM_VER_MASK 0x3
|
||||
#define WL18XX_ROM_VER_OFFSET 0
|
||||
#define WL18XX_METAL_VER_MASK 0xC
|
||||
#define WL18XX_METAL_VER_OFFSET 2
|
||||
#define WL18XX_NEW_METAL_VER_MASK 0x180
|
||||
#define WL18XX_NEW_METAL_VER_OFFSET 7
|
||||
|
||||
#define WL18XX_REG_FUSE_DATA_2_3 0xA02614
|
||||
#define WL18XX_RDL_VER_MASK 0x1f00
|
||||
#define WL18XX_RDL_VER_OFFSET 8
|
||||
|
||||
#define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602
|
||||
#define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606
|
||||
@ -188,4 +198,23 @@ enum {
|
||||
NUM_BOARD_TYPES,
|
||||
};
|
||||
|
||||
enum {
|
||||
RDL_NONE = 0,
|
||||
RDL_1_HP = 1,
|
||||
RDL_2_SP = 2,
|
||||
RDL_3_HP = 3,
|
||||
RDL_4_SP = 4,
|
||||
|
||||
_RDL_LAST,
|
||||
RDL_MAX = _RDL_LAST - 1,
|
||||
};
|
||||
|
||||
static const char * const rdl_names[] = {
|
||||
[RDL_NONE] = "",
|
||||
[RDL_1_HP] = "1853 SISO",
|
||||
[RDL_2_SP] = "1857 MIMO",
|
||||
[RDL_3_HP] = "1893 SISO",
|
||||
[RDL_4_SP] = "1897 MIMO",
|
||||
};
|
||||
|
||||
#endif /* __REG_H__ */
|
||||
|
@ -29,7 +29,7 @@
|
||||
#define WL18XX_IFTYPE_VER 5
|
||||
#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_MINOR_VER 28
|
||||
#define WL18XX_MINOR_VER 39
|
||||
|
||||
#define WL18XX_CMD_MAX_SIZE 740
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
|
||||
#define WL18XX_NUM_MAC_ADDRESSES 3
|
||||
|
||||
#define WL18XX_RX_BA_MAX_SESSIONS 5
|
||||
|
||||
struct wl18xx_priv {
|
||||
/* buffer for sending commands to FW */
|
||||
u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
|
||||
|
@ -1736,6 +1736,35 @@ out:
|
||||
|
||||
}
|
||||
|
||||
int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
s8 *avg_rssi)
|
||||
{
|
||||
struct acx_roaming_stats *acx;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx roaming statistics");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->role_id = wlvif->role_id;
|
||||
ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL,
|
||||
acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx roaming statistics failed: %d", ret);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*avg_rssi = acx->rssi_beacon;
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* Set the global behaviour of RX filters - On/Off + default action */
|
||||
int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
|
||||
|
@ -728,8 +728,6 @@ struct wl1271_acx_ht_information {
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
#define RX_BA_MAX_SESSIONS 3
|
||||
|
||||
struct wl1271_acx_ba_initiator_policy {
|
||||
struct acx_header header;
|
||||
|
||||
@ -955,6 +953,18 @@ struct acx_rx_filter_cfg {
|
||||
u8 fields[0];
|
||||
} __packed;
|
||||
|
||||
struct acx_roaming_stats {
|
||||
struct acx_header header;
|
||||
|
||||
u8 role_id;
|
||||
u8 pad[3];
|
||||
u32 missed_beacons;
|
||||
u8 snr_data;
|
||||
u8 snr_bacon;
|
||||
s8 rssi_data;
|
||||
s8 rssi_beacon;
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0000,
|
||||
ACX_MEM_CFG = 0x0001,
|
||||
@ -1112,6 +1122,8 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
|
||||
int wl1271_acx_fm_coex(struct wl1271 *wl);
|
||||
int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
|
||||
int wl12xx_acx_config_hangover(struct wl1271 *wl);
|
||||
int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
s8 *avg_rssi);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
|
||||
|
@ -327,6 +327,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
|
||||
wl->links[link].prev_freed_pkts =
|
||||
wl->fw_status_2->counters.tx_lnk_free_pkts[link];
|
||||
wl->links[link].wlvif = wlvif;
|
||||
|
||||
/*
|
||||
* Take saved value for total freed packets from wlvif, in case this is
|
||||
* recovery/resume
|
||||
*/
|
||||
if (wlvif->bss_type != BSS_TYPE_AP_BSS)
|
||||
wl->links[link].total_freed_pkts = wlvif->total_freed_pkts;
|
||||
|
||||
*hlid = link;
|
||||
|
||||
wl->active_link_count++;
|
||||
@ -358,6 +366,26 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
|
||||
wl1271_tx_reset_link_queues(wl, *hlid);
|
||||
wl->links[*hlid].wlvif = NULL;
|
||||
|
||||
if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
|
||||
(wlvif->bss_type == BSS_TYPE_AP_BSS &&
|
||||
*hlid == wlvif->ap.bcast_hlid)) {
|
||||
/*
|
||||
* save the total freed packets in the wlvif, in case this is
|
||||
* recovery or suspend
|
||||
*/
|
||||
wlvif->total_freed_pkts = wl->links[*hlid].total_freed_pkts;
|
||||
|
||||
/*
|
||||
* increment the initial seq number on recovery to account for
|
||||
* transmitted packets that we haven't yet got in the FW status
|
||||
*/
|
||||
if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
|
||||
wlvif->total_freed_pkts +=
|
||||
WL1271_TX_SQN_POST_RECOVERY_PADDING;
|
||||
}
|
||||
|
||||
wl->links[*hlid].total_freed_pkts = 0;
|
||||
|
||||
*hlid = WL12XX_INVALID_LINK_ID;
|
||||
wl->active_link_count--;
|
||||
WARN_ON_ONCE(wl->active_link_count < 0);
|
||||
@ -609,6 +637,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
if (ret < 0)
|
||||
goto out_free_global;
|
||||
|
||||
/* use the previous security seq, if this is a recovery/resume */
|
||||
wl->links[wlvif->ap.bcast_hlid].total_freed_pkts =
|
||||
wlvif->total_freed_pkts;
|
||||
|
||||
cmd->role_id = wlvif->role_id;
|
||||
cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
|
||||
cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
|
||||
|
@ -89,25 +89,24 @@ extern u32 wl12xx_debug_level;
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* TODO: use pr_debug_hex_dump when it becomes available */
|
||||
#define wl1271_dump(level, prefix, buf, len) \
|
||||
do { \
|
||||
if (level & wl12xx_debug_level) \
|
||||
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
|
||||
DUMP_PREFIX_OFFSET, 16, 1, \
|
||||
buf, \
|
||||
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
|
||||
0); \
|
||||
#define wl1271_dump(level, prefix, buf, len) \
|
||||
do { \
|
||||
if (level & wl12xx_debug_level) \
|
||||
print_hex_dump_debug(DRIVER_PREFIX prefix, \
|
||||
DUMP_PREFIX_OFFSET, 16, 1, \
|
||||
buf, \
|
||||
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
|
||||
0); \
|
||||
} while (0)
|
||||
|
||||
#define wl1271_dump_ascii(level, prefix, buf, len) \
|
||||
do { \
|
||||
if (level & wl12xx_debug_level) \
|
||||
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
|
||||
DUMP_PREFIX_OFFSET, 16, 1, \
|
||||
buf, \
|
||||
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
|
||||
true); \
|
||||
#define wl1271_dump_ascii(level, prefix, buf, len) \
|
||||
do { \
|
||||
if (level & wl12xx_debug_level) \
|
||||
print_hex_dump_debug(DRIVER_PREFIX prefix, \
|
||||
DUMP_PREFIX_OFFSET, 16, 1, \
|
||||
buf, \
|
||||
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
|
||||
true); \
|
||||
} while (0)
|
||||
|
||||
#endif /* __DEBUG_H__ */
|
||||
|
@ -598,8 +598,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
|
||||
VIF_STATE_PRINT_INT(last_rssi_event);
|
||||
VIF_STATE_PRINT_INT(ba_support);
|
||||
VIF_STATE_PRINT_INT(ba_allowed);
|
||||
VIF_STATE_PRINT_LLHEX(tx_security_seq);
|
||||
VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
|
||||
VIF_STATE_PRINT_LLHEX(total_freed_pkts);
|
||||
}
|
||||
|
||||
#undef VIF_STATE_PRINT_INT
|
||||
|
@ -237,6 +237,14 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
|
||||
!test_bit(wlvif->role_id , &roles_bitmap))
|
||||
continue;
|
||||
|
||||
vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
|
||||
/* don't attempt roaming in case of p2p */
|
||||
if (wlvif->p2p) {
|
||||
ieee80211_connection_loss(vif);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the work is already queued, it should take place.
|
||||
* We don't want to delay the connection loss
|
||||
@ -246,7 +254,6 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
|
||||
&wlvif->connection_loss_work,
|
||||
msecs_to_jiffies(delay));
|
||||
|
||||
vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
ieee80211_cqm_rssi_notify(
|
||||
vif,
|
||||
NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
|
||||
|
@ -108,8 +108,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy,
|
||||
|
||||
}
|
||||
|
||||
if (likely(wl->state == WLCORE_STATE_ON))
|
||||
wlcore_regdomain_config(wl);
|
||||
wlcore_regdomain_config(wl);
|
||||
}
|
||||
|
||||
static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
@ -332,10 +331,9 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
u8 hlid, u8 tx_pkts)
|
||||
{
|
||||
bool fw_ps, single_link;
|
||||
bool fw_ps;
|
||||
|
||||
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
single_link = (wl->active_link_count == 1);
|
||||
|
||||
/*
|
||||
* Wake up from high level PS if the STA is asleep with too little
|
||||
@ -348,8 +346,13 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
|
||||
* Start high-level PS if the STA is asleep with enough blocks in FW.
|
||||
* Make an exception if this is the only connected link. In this
|
||||
* case FW-memory congestion is less of a problem.
|
||||
* Note that a single connected STA means 3 active links, since we must
|
||||
* account for the global and broadcast AP links. The "fw_ps" check
|
||||
* assures us the third link is a STA connected to the AP. Otherwise
|
||||
* the FW would not set the PSM bit.
|
||||
*/
|
||||
else if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
else if (wl->active_link_count > 3 && fw_ps &&
|
||||
tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
wl12xx_ps_link_start(wl, wlvif, hlid, true);
|
||||
}
|
||||
|
||||
@ -414,13 +417,21 @@ static int wlcore_fw_status(struct wl1271 *wl,
|
||||
|
||||
|
||||
for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) {
|
||||
u8 diff;
|
||||
lnk = &wl->links[i];
|
||||
/* prevent wrap-around in freed-packets counter */
|
||||
lnk->allocated_pkts -=
|
||||
(status_2->counters.tx_lnk_free_pkts[i] -
|
||||
lnk->prev_freed_pkts) & 0xff;
|
||||
|
||||
/* prevent wrap-around in freed-packets counter */
|
||||
diff = (status_2->counters.tx_lnk_free_pkts[i] -
|
||||
lnk->prev_freed_pkts) & 0xff;
|
||||
|
||||
if (diff == 0)
|
||||
continue;
|
||||
|
||||
lnk->allocated_pkts -= diff;
|
||||
lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i];
|
||||
|
||||
/* accumulate the prev_freed_pkts counter */
|
||||
lnk->total_freed_pkts += diff;
|
||||
}
|
||||
|
||||
/* prevent wrap-around in total blocks counter */
|
||||
@ -640,6 +651,25 @@ static irqreturn_t wlcore_irq(int irq, void *cookie)
|
||||
unsigned long flags;
|
||||
struct wl1271 *wl = cookie;
|
||||
|
||||
/* complete the ELP completion */
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
|
||||
if (wl->elp_compl) {
|
||||
complete(wl->elp_compl);
|
||||
wl->elp_compl = NULL;
|
||||
}
|
||||
|
||||
if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
|
||||
/* don't enqueue a work right now. mark it as pending */
|
||||
set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
|
||||
wl1271_debug(DEBUG_IRQ, "should not enqueue work");
|
||||
disable_irq_nosync(wl->irq);
|
||||
pm_wakeup_event(wl->dev, 0);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
/* TX might be handled here, avoid redundant work */
|
||||
set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
|
||||
cancel_work_sync(&wl->tx_work);
|
||||
@ -919,18 +949,6 @@ static void wl1271_recovery_work(struct work_struct *work)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance security sequence number to overcome potential progress
|
||||
* in the firmware during recovery. This doens't hurt if the network is
|
||||
* not encrypted.
|
||||
*/
|
||||
wl12xx_for_each_wlvif(wl, wlvif) {
|
||||
if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
|
||||
test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
|
||||
wlvif->tx_security_seq +=
|
||||
WL1271_TX_SQN_POST_RECOVERY_PADDING;
|
||||
}
|
||||
|
||||
/* Prevent spurious TX during FW restart */
|
||||
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART);
|
||||
|
||||
@ -2523,6 +2541,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
}
|
||||
deinit:
|
||||
wl12xx_tx_reset_wlvif(wl, wlvif);
|
||||
|
||||
/* clear all hlids (except system_hlid) */
|
||||
wlvif->dev_hlid = WL12XX_INVALID_LINK_ID;
|
||||
|
||||
@ -2546,7 +2566,6 @@ deinit:
|
||||
|
||||
dev_kfree_skb(wlvif->probereq);
|
||||
wlvif->probereq = NULL;
|
||||
wl12xx_tx_reset_wlvif(wl, wlvif);
|
||||
if (wl->last_wlvif == wlvif)
|
||||
wl->last_wlvif = NULL;
|
||||
list_del(&wlvif->list);
|
||||
@ -2860,10 +2879,6 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
wlvif->sta.klv_template_id,
|
||||
ACX_KEEP_ALIVE_TPL_INVALID);
|
||||
|
||||
/* reset TX security counters on a clean disconnect */
|
||||
wlvif->tx_security_last_seq_lsb = 0;
|
||||
wlvif->tx_security_seq = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3262,6 +3277,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
||||
u32 tx_seq_32 = 0;
|
||||
u16 tx_seq_16 = 0;
|
||||
u8 key_type;
|
||||
u8 hlid;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
|
||||
|
||||
@ -3271,6 +3287,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
||||
key_conf->keylen, key_conf->flags);
|
||||
wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
|
||||
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS)
|
||||
if (sta) {
|
||||
struct wl1271_station *wl_sta = (void *)sta->drv_priv;
|
||||
hlid = wl_sta->hlid;
|
||||
} else {
|
||||
hlid = wlvif->ap.bcast_hlid;
|
||||
}
|
||||
else
|
||||
hlid = wlvif->sta.hlid;
|
||||
|
||||
if (hlid != WL12XX_INVALID_LINK_ID) {
|
||||
u64 tx_seq = wl->links[hlid].total_freed_pkts;
|
||||
tx_seq_32 = WL1271_TX_SECURITY_HI32(tx_seq);
|
||||
tx_seq_16 = WL1271_TX_SECURITY_LO16(tx_seq);
|
||||
}
|
||||
|
||||
switch (key_conf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
@ -3280,22 +3312,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
key_type = KEY_TKIP;
|
||||
|
||||
key_conf->hw_key_idx = key_conf->keyidx;
|
||||
tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
|
||||
tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
key_type = KEY_AES;
|
||||
|
||||
key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
|
||||
tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
|
||||
tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
|
||||
break;
|
||||
case WL1271_CIPHER_SUITE_GEM:
|
||||
key_type = KEY_GEM;
|
||||
tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq);
|
||||
tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq);
|
||||
break;
|
||||
default:
|
||||
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
|
||||
@ -3358,6 +3382,10 @@ void wlcore_regdomain_config(struct wl1271 *wl)
|
||||
return;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@ -4499,6 +4527,9 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* use the previous security seq, if this is a recovery/resume */
|
||||
wl->links[wl_sta->hlid].total_freed_pkts = wl_sta->total_freed_pkts;
|
||||
|
||||
set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map);
|
||||
memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
|
||||
wl->active_sta_count++;
|
||||
@ -4507,12 +4538,37 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
|
||||
|
||||
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
|
||||
{
|
||||
struct wl1271_station *wl_sta;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
|
||||
if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
|
||||
return;
|
||||
|
||||
clear_bit(hlid, wlvif->ap.sta_hlid_map);
|
||||
__clear_bit(hlid, &wl->ap_ps_map);
|
||||
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
|
||||
/*
|
||||
* save the last used PN in the private part of iee80211_sta,
|
||||
* in case of recovery/suspend
|
||||
*/
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
|
||||
if (sta) {
|
||||
wl_sta = (void *)sta->drv_priv;
|
||||
wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
|
||||
|
||||
/*
|
||||
* increment the initial seq number on recovery to account for
|
||||
* transmitted packets that we haven't yet got in the FW status
|
||||
*/
|
||||
if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
|
||||
wl_sta->total_freed_pkts +=
|
||||
WL1271_TX_SQN_POST_RECOVERY_PADDING;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
wl12xx_free_link(wl, wlvif, &hlid);
|
||||
wl->active_sta_count--;
|
||||
|
||||
@ -4616,13 +4672,11 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
|
||||
enum ieee80211_sta_state new_state)
|
||||
{
|
||||
struct wl1271_station *wl_sta;
|
||||
u8 hlid;
|
||||
bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS;
|
||||
bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;
|
||||
int ret;
|
||||
|
||||
wl_sta = (struct wl1271_station *)sta->drv_priv;
|
||||
hlid = wl_sta->hlid;
|
||||
|
||||
/* Add station (AP mode) */
|
||||
if (is_ap &&
|
||||
@ -4648,12 +4702,12 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
|
||||
/* Authorize station (AP mode) */
|
||||
if (is_ap &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
ret = wl12xx_cmd_set_peer_state(wl, wlvif, hlid);
|
||||
ret = wl12xx_cmd_set_peer_state(wl, wlvif, wl_sta->hlid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true,
|
||||
hlid);
|
||||
wl_sta->hlid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -4784,7 +4838,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
||||
break;
|
||||
}
|
||||
|
||||
if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) {
|
||||
if (wl->ba_rx_session_count >= wl->ba_rx_session_count_max) {
|
||||
ret = -EBUSY;
|
||||
wl1271_error("exceeded max RX BA sessions");
|
||||
break;
|
||||
@ -4946,7 +5000,7 @@ out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void wlcore_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
||||
@ -5092,6 +5146,39 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
|
||||
}
|
||||
|
||||
static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
s8 *rssi_dbm)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON))
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
@ -5291,6 +5378,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
||||
.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
|
||||
.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
|
||||
.sta_rc_update = wlcore_op_sta_rc_update,
|
||||
.get_rssi = wlcore_op_get_rssi,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
@ -5930,35 +6018,6 @@ int wlcore_free_hw(struct wl1271 *wl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wlcore_free_hw);
|
||||
|
||||
static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
|
||||
{
|
||||
struct wl1271 *wl = cookie;
|
||||
unsigned long flags;
|
||||
|
||||
wl1271_debug(DEBUG_IRQ, "IRQ");
|
||||
|
||||
/* complete the ELP completion */
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
|
||||
if (wl->elp_compl) {
|
||||
complete(wl->elp_compl);
|
||||
wl->elp_compl = NULL;
|
||||
}
|
||||
|
||||
if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
|
||||
/* don't enqueue a work right now. mark it as pending */
|
||||
set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
|
||||
wl1271_debug(DEBUG_IRQ, "should not enqueue work");
|
||||
disable_irq_nosync(wl->irq);
|
||||
pm_wakeup_event(wl->dev, 0);
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
static void wlcore_nvs_cb(const struct firmware *fw, void *context)
|
||||
{
|
||||
struct wl1271 *wl = context;
|
||||
@ -6000,9 +6059,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
|
||||
else
|
||||
irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
|
||||
|
||||
ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq,
|
||||
irqflags,
|
||||
pdev->name, wl);
|
||||
ret = request_threaded_irq(wl->irq, NULL, wlcore_irq,
|
||||
irqflags, pdev->name, wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("request_irq() failed: %d", ret);
|
||||
goto out_free_nvs;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define WL1271_WAKEUP_TIMEOUT 500
|
||||
|
||||
#define ELP_ENTRY_DELAY 30
|
||||
#define ELP_ENTRY_DELAY_FORCE_PS 5
|
||||
|
||||
void wl1271_elp_work(struct work_struct *work)
|
||||
{
|
||||
@ -98,7 +99,8 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
||||
return;
|
||||
}
|
||||
|
||||
timeout = ELP_ENTRY_DELAY;
|
||||
timeout = wl->conf.conn.forced_ps ?
|
||||
ELP_ENTRY_DELAY_FORCE_PS : ELP_ENTRY_DELAY;
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(timeout));
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "wlcore.h"
|
||||
#include "debug.h"
|
||||
@ -104,7 +105,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
u8 hlid)
|
||||
{
|
||||
bool fw_ps, single_link;
|
||||
bool fw_ps;
|
||||
u8 tx_pkts;
|
||||
|
||||
if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
|
||||
@ -112,15 +113,19 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
|
||||
|
||||
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
||||
tx_pkts = wl->links[hlid].allocated_pkts;
|
||||
single_link = (wl->active_link_count == 1);
|
||||
|
||||
/*
|
||||
* if in FW PS and there is enough data in FW we can put the link
|
||||
* into high-level PS and clean out its TX queues.
|
||||
* Make an exception if this is the only connected link. In this
|
||||
* case FW-memory congestion is less of a problem.
|
||||
* Note that a single connected STA means 3 active links, since we must
|
||||
* account for the global and broadcast AP links. The "fw_ps" check
|
||||
* assures us the third link is a STA connected to the AP. Otherwise
|
||||
* the FW would not set the PSM bit.
|
||||
*/
|
||||
if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
if (wl->active_link_count > 3 && fw_ps &&
|
||||
tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
|
||||
wl12xx_ps_link_start(wl, wlvif, hlid, true);
|
||||
}
|
||||
|
||||
@ -639,6 +644,7 @@ next:
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
if (!skb &&
|
||||
test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
|
||||
int q;
|
||||
@ -652,7 +658,6 @@ next:
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
}
|
||||
|
||||
out:
|
||||
return skb;
|
||||
}
|
||||
|
||||
@ -928,25 +933,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
|
||||
|
||||
wl->stats.retry_count += result->ack_failures;
|
||||
|
||||
/*
|
||||
* update sequence number only when relevant, i.e. only in
|
||||
* sessions of TKIP, AES and GEM (not in open or WEP sessions)
|
||||
*/
|
||||
if (info->control.hw_key &&
|
||||
(info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
|
||||
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
|
||||
u8 fw_lsb = result->tx_security_sequence_number_lsb;
|
||||
u8 cur_lsb = wlvif->tx_security_last_seq_lsb;
|
||||
|
||||
/*
|
||||
* update security sequence number, taking care of potential
|
||||
* wrap-around
|
||||
*/
|
||||
wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff;
|
||||
wlvif->tx_security_last_seq_lsb = fw_lsb;
|
||||
}
|
||||
|
||||
/* remove private header from packet */
|
||||
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
|
||||
|
||||
@ -1061,7 +1047,8 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
|
||||
/* TX failure */
|
||||
for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
|
||||
i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) {
|
||||
/* this calls wl12xx_free_link */
|
||||
wl1271_free_sta(wl, wlvif, i);
|
||||
} else {
|
||||
@ -1304,7 +1291,7 @@ bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl,
|
||||
{
|
||||
int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
|
||||
|
||||
WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock));
|
||||
assert_spin_locked(&wl->wl_lock);
|
||||
return test_bit(reason, &wl->queue_stop_reasons[hwq]);
|
||||
}
|
||||
|
||||
@ -1313,6 +1300,6 @@ bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
{
|
||||
int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue);
|
||||
|
||||
WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock));
|
||||
assert_spin_locked(&wl->wl_lock);
|
||||
return !!wl->queue_stop_reasons[hwq];
|
||||
}
|
||||
|
@ -390,6 +390,9 @@ struct wl1271 {
|
||||
/* number of currently active RX BA sessions */
|
||||
int ba_rx_session_count;
|
||||
|
||||
/* Maximum number of supported RX BA sessions */
|
||||
int ba_rx_session_count_max;
|
||||
|
||||
/* AP-mode - number of currently connected stations */
|
||||
int active_sta_count;
|
||||
|
||||
|
@ -274,6 +274,13 @@ struct wl1271_link {
|
||||
|
||||
/* The wlvif this link belongs to. Might be null for global links */
|
||||
struct wl12xx_vif *wlvif;
|
||||
|
||||
/*
|
||||
* total freed FW packets on the link - used for tracking the
|
||||
* AES/TKIP PN across recoveries. Re-initialized each time
|
||||
* from the wl1271_station structure.
|
||||
*/
|
||||
u64 total_freed_pkts;
|
||||
};
|
||||
|
||||
#define WL1271_MAX_RX_FILTERS 5
|
||||
@ -318,6 +325,13 @@ struct wl12xx_rx_filter {
|
||||
struct wl1271_station {
|
||||
u8 hlid;
|
||||
bool in_connection;
|
||||
|
||||
/*
|
||||
* total freed FW packets on the link to the STA - used for tracking the
|
||||
* AES/TKIP PN across recoveries. Re-initialized each time from the
|
||||
* wl1271_station structure.
|
||||
*/
|
||||
u64 total_freed_pkts;
|
||||
};
|
||||
|
||||
struct wl12xx_vif {
|
||||
@ -449,16 +463,15 @@ struct wl12xx_vif {
|
||||
*/
|
||||
struct {
|
||||
u8 persistent[0];
|
||||
/*
|
||||
* Security sequence number
|
||||
* bits 0-15: lower 16 bits part of sequence number
|
||||
* bits 16-47: higher 32 bits part of sequence number
|
||||
* bits 48-63: not in use
|
||||
*/
|
||||
u64 tx_security_seq;
|
||||
|
||||
/* 8 bits of the last sequence number in use */
|
||||
u8 tx_security_last_seq_lsb;
|
||||
/*
|
||||
* total freed FW packets on the link - used for
|
||||
* storing the AES/TKIP PN during recovery, as this
|
||||
* structure is not zeroed out.
|
||||
* For STA this holds the PN of the link to the AP.
|
||||
* For AP this holds the PN of the broadcast link.
|
||||
*/
|
||||
u64 total_freed_pkts;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -347,6 +347,21 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
|
||||
return (s8)gain;
|
||||
}
|
||||
|
||||
static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
|
||||
{
|
||||
SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
|
||||
SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
|
||||
SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
|
||||
SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
|
||||
SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
|
||||
SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
|
||||
SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
|
||||
SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
|
||||
SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
|
||||
SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
|
||||
SSB_SPROM2_MAXP_A_LO_SHIFT);
|
||||
}
|
||||
|
||||
static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
{
|
||||
u16 loc[3];
|
||||
@ -369,6 +384,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
|
||||
SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
|
||||
SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
|
||||
SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
|
||||
if (out->revision == 1)
|
||||
SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
|
||||
SSB_SPROM1_BINF_CCODE_SHIFT);
|
||||
@ -395,8 +411,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
SSB_SPROM1_ITSSI_A_SHIFT);
|
||||
SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
|
||||
SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
|
||||
if (out->revision >= 2)
|
||||
SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
|
||||
|
||||
SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
|
||||
SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
|
||||
|
||||
@ -407,6 +422,8 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
|
||||
SSB_SPROM1_AGAIN_A,
|
||||
SSB_SPROM1_AGAIN_A_SHIFT);
|
||||
if (out->revision >= 2)
|
||||
sprom_extract_r23(out, in);
|
||||
}
|
||||
|
||||
/* Revs 4 5 and 8 have partially shared layout */
|
||||
@ -464,6 +481,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
|
||||
SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
|
||||
SSB_SPROM4_ETHPHY_ET1A_SHIFT);
|
||||
SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
|
||||
SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
|
||||
if (out->revision == 4) {
|
||||
SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
|
||||
SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
|
||||
@ -535,6 +553,7 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
|
||||
sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
|
||||
|
||||
SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
|
||||
SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
|
||||
SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
|
||||
SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
|
||||
SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
|
||||
|
@ -173,6 +173,60 @@ struct bcma_host_ops {
|
||||
#define BCMA_CHIP_ID_BCM53572 53572
|
||||
#define BCMA_PKG_ID_BCM47188 9
|
||||
|
||||
/* Board types (on PCI usually equals to the subsystem dev id) */
|
||||
/* BCM4313 */
|
||||
#define BCMA_BOARD_TYPE_BCM94313BU 0X050F
|
||||
#define BCMA_BOARD_TYPE_BCM94313HM 0X0510
|
||||
#define BCMA_BOARD_TYPE_BCM94313EPA 0X0511
|
||||
#define BCMA_BOARD_TYPE_BCM94313HMG 0X051C
|
||||
/* BCM4716 */
|
||||
#define BCMA_BOARD_TYPE_BCM94716NR2 0X04CD
|
||||
/* BCM43224 */
|
||||
#define BCMA_BOARD_TYPE_BCM943224X21 0X056E
|
||||
#define BCMA_BOARD_TYPE_BCM943224X21_FCC 0X00D1
|
||||
#define BCMA_BOARD_TYPE_BCM943224X21B 0X00E9
|
||||
#define BCMA_BOARD_TYPE_BCM943224M93 0X008B
|
||||
#define BCMA_BOARD_TYPE_BCM943224M93A 0X0090
|
||||
#define BCMA_BOARD_TYPE_BCM943224X16 0X0093
|
||||
#define BCMA_BOARD_TYPE_BCM94322X9 0X008D
|
||||
#define BCMA_BOARD_TYPE_BCM94322M35E 0X008E
|
||||
/* BCM43228 */
|
||||
#define BCMA_BOARD_TYPE_BCM943228BU8 0X0540
|
||||
#define BCMA_BOARD_TYPE_BCM943228BU9 0X0541
|
||||
#define BCMA_BOARD_TYPE_BCM943228BU 0X0542
|
||||
#define BCMA_BOARD_TYPE_BCM943227HM4L 0X0543
|
||||
#define BCMA_BOARD_TYPE_BCM943227HMB 0X0544
|
||||
#define BCMA_BOARD_TYPE_BCM943228HM4L 0X0545
|
||||
#define BCMA_BOARD_TYPE_BCM943228SD 0X0573
|
||||
/* BCM4331 */
|
||||
#define BCMA_BOARD_TYPE_BCM94331X19 0X00D6
|
||||
#define BCMA_BOARD_TYPE_BCM94331X28 0X00E4
|
||||
#define BCMA_BOARD_TYPE_BCM94331X28B 0X010E
|
||||
#define BCMA_BOARD_TYPE_BCM94331PCIEBT3AX 0X00E4
|
||||
#define BCMA_BOARD_TYPE_BCM94331X12_2G 0X00EC
|
||||
#define BCMA_BOARD_TYPE_BCM94331X12_5G 0X00ED
|
||||
#define BCMA_BOARD_TYPE_BCM94331X29B 0X00EF
|
||||
#define BCMA_BOARD_TYPE_BCM94331CSAX 0X00EF
|
||||
#define BCMA_BOARD_TYPE_BCM94331X19C 0X00F5
|
||||
#define BCMA_BOARD_TYPE_BCM94331X33 0X00F4
|
||||
#define BCMA_BOARD_TYPE_BCM94331BU 0X0523
|
||||
#define BCMA_BOARD_TYPE_BCM94331S9BU 0X0524
|
||||
#define BCMA_BOARD_TYPE_BCM94331MC 0X0525
|
||||
#define BCMA_BOARD_TYPE_BCM94331MCI 0X0526
|
||||
#define BCMA_BOARD_TYPE_BCM94331PCIEBT4 0X0527
|
||||
#define BCMA_BOARD_TYPE_BCM94331HM 0X0574
|
||||
#define BCMA_BOARD_TYPE_BCM94331PCIEDUAL 0X059B
|
||||
#define BCMA_BOARD_TYPE_BCM94331MCH5 0X05A9
|
||||
#define BCMA_BOARD_TYPE_BCM94331CS 0X05C6
|
||||
#define BCMA_BOARD_TYPE_BCM94331CD 0X05DA
|
||||
/* BCM53572 */
|
||||
#define BCMA_BOARD_TYPE_BCM953572BU 0X058D
|
||||
#define BCMA_BOARD_TYPE_BCM953572NR2 0X058E
|
||||
#define BCMA_BOARD_TYPE_BCM947188NR2 0X058F
|
||||
#define BCMA_BOARD_TYPE_BCM953572SDRNR2 0X0590
|
||||
/* BCM43142 */
|
||||
#define BCMA_BOARD_TYPE_BCM943142HM 0X05E0
|
||||
|
||||
struct bcma_device {
|
||||
struct bcma_bus *bus;
|
||||
struct bcma_device_id id;
|
||||
|
@ -340,13 +340,61 @@ enum ssb_bustype {
|
||||
#define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */
|
||||
#define SSB_BOARDVENDOR_HP 0x0E11 /* HP */
|
||||
/* board_type */
|
||||
#define SSB_BOARD_BCM94301CB 0x0406
|
||||
#define SSB_BOARD_BCM94301MP 0x0407
|
||||
#define SSB_BOARD_BU4309 0x040A
|
||||
#define SSB_BOARD_BCM94309CB 0x040B
|
||||
#define SSB_BOARD_BCM4309MP 0x040C
|
||||
#define SSB_BOARD_BU4306 0x0416
|
||||
#define SSB_BOARD_BCM94306MP 0x0418
|
||||
#define SSB_BOARD_BCM4309G 0x0421
|
||||
#define SSB_BOARD_BCM4306CB 0x0417
|
||||
#define SSB_BOARD_BCM4309MP 0x040C
|
||||
#define SSB_BOARD_BCM94306PC 0x0425 /* pcmcia 3.3v 4306 card */
|
||||
#define SSB_BOARD_BCM94306CBSG 0x042B /* with SiGe PA */
|
||||
#define SSB_BOARD_PCSG94306 0x042D /* with SiGe PA */
|
||||
#define SSB_BOARD_BU4704SD 0x042E /* with sdram */
|
||||
#define SSB_BOARD_BCM94704AGR 0x042F /* dual 11a/11g Router */
|
||||
#define SSB_BOARD_BCM94308MP 0x0430 /* 11a-only minipci */
|
||||
#define SSB_BOARD_BU4318 0x0447
|
||||
#define SSB_BOARD_CB4318 0x0448
|
||||
#define SSB_BOARD_MPG4318 0x0449
|
||||
#define SSB_BOARD_MP4318 0x044A
|
||||
#define SSB_BOARD_BU4306 0x0416
|
||||
#define SSB_BOARD_BU4309 0x040A
|
||||
#define SSB_BOARD_SD4318 0x044B
|
||||
#define SSB_BOARD_BCM94306P 0x044C /* with SiGe */
|
||||
#define SSB_BOARD_BCM94303MP 0x044E
|
||||
#define SSB_BOARD_BCM94306MPM 0x0450
|
||||
#define SSB_BOARD_BCM94306MPL 0x0453
|
||||
#define SSB_BOARD_PC4303 0x0454 /* pcmcia */
|
||||
#define SSB_BOARD_BCM94306MPLNA 0x0457
|
||||
#define SSB_BOARD_BCM94306MPH 0x045B
|
||||
#define SSB_BOARD_BCM94306PCIV 0x045C
|
||||
#define SSB_BOARD_BCM94318MPGH 0x0463
|
||||
#define SSB_BOARD_BU4311 0x0464
|
||||
#define SSB_BOARD_BCM94311MC 0x0465
|
||||
#define SSB_BOARD_BCM94311MCAG 0x0466
|
||||
/* 4321 boards */
|
||||
#define SSB_BOARD_BU4321 0x046B
|
||||
#define SSB_BOARD_BU4321E 0x047C
|
||||
#define SSB_BOARD_MP4321 0x046C
|
||||
#define SSB_BOARD_CB2_4321 0x046D
|
||||
#define SSB_BOARD_CB2_4321_AG 0x0066
|
||||
#define SSB_BOARD_MC4321 0x046E
|
||||
/* 4325 boards */
|
||||
#define SSB_BOARD_BCM94325DEVBU 0x0490
|
||||
#define SSB_BOARD_BCM94325BGABU 0x0491
|
||||
#define SSB_BOARD_BCM94325SDGWB 0x0492
|
||||
#define SSB_BOARD_BCM94325SDGMDL 0x04AA
|
||||
#define SSB_BOARD_BCM94325SDGMDL2 0x04C6
|
||||
#define SSB_BOARD_BCM94325SDGMDL3 0x04C9
|
||||
#define SSB_BOARD_BCM94325SDABGWBA 0x04E1
|
||||
/* 4322 boards */
|
||||
#define SSB_BOARD_BCM94322MC 0x04A4
|
||||
#define SSB_BOARD_BCM94322USB 0x04A8 /* dualband */
|
||||
#define SSB_BOARD_BCM94322HM 0x04B0
|
||||
#define SSB_BOARD_BCM94322USB2D 0x04Bf /* single band discrete front end */
|
||||
/* 4312 boards */
|
||||
#define SSB_BOARD_BU4312 0x048A
|
||||
#define SSB_BOARD_BCM4312MCGSG 0x04B5
|
||||
/* chip_package */
|
||||
#define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */
|
||||
#define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */
|
||||
|
@ -289,11 +289,11 @@
|
||||
#define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5
|
||||
#define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */
|
||||
#define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */
|
||||
#define SSB_SPROM4_ANTAVAIL 0x005D /* Antenna available bitfields */
|
||||
#define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */
|
||||
#define SSB_SPROM4_ANTAVAIL_A_SHIFT 0
|
||||
#define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */
|
||||
#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8
|
||||
#define SSB_SPROM4_ANTAVAIL 0x005C /* Antenna available bitfields */
|
||||
#define SSB_SPROM4_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */
|
||||
#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 0
|
||||
#define SSB_SPROM4_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */
|
||||
#define SSB_SPROM4_ANTAVAIL_A_SHIFT 8
|
||||
#define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */
|
||||
#define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */
|
||||
#define SSB_SPROM4_AGAIN0_SHIFT 0
|
||||
|
@ -232,7 +232,7 @@ struct bt_sock_list {
|
||||
};
|
||||
|
||||
int bt_sock_register(int proto, const struct net_proto_family *ops);
|
||||
int bt_sock_unregister(int proto);
|
||||
void bt_sock_unregister(int proto);
|
||||
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
|
||||
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
|
||||
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
@ -260,12 +260,22 @@ struct l2cap_ctrl {
|
||||
__u8 retries;
|
||||
};
|
||||
|
||||
struct hci_dev;
|
||||
|
||||
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
|
||||
|
||||
struct hci_req_ctrl {
|
||||
bool start;
|
||||
hci_req_complete_t complete;
|
||||
};
|
||||
|
||||
struct bt_skb_cb {
|
||||
__u8 pkt_type;
|
||||
__u8 incoming;
|
||||
__u16 expect;
|
||||
__u8 force_active;
|
||||
struct l2cap_ctrl control;
|
||||
struct hci_req_ctrl req;
|
||||
};
|
||||
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
|
||||
|
||||
|
@ -119,10 +119,16 @@ enum {
|
||||
HCI_CONNECTABLE,
|
||||
HCI_DISCOVERABLE,
|
||||
HCI_LINK_SECURITY,
|
||||
HCI_PENDING_CLASS,
|
||||
HCI_PERIODIC_INQ,
|
||||
HCI_FAST_CONNECTABLE,
|
||||
};
|
||||
|
||||
/* A mask for the flags that are supposed to remain when a reset happens
|
||||
* or the HCI device is closed.
|
||||
*/
|
||||
#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
|
||||
BIT(HCI_FAST_CONNECTABLE))
|
||||
|
||||
/* HCI ioctl defines */
|
||||
#define HCIDEVUP _IOW('H', 201, int)
|
||||
#define HCIDEVDOWN _IOW('H', 202, int)
|
||||
@ -881,12 +887,25 @@ struct hci_rp_read_data_block_size {
|
||||
__le16 num_blocks;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b
|
||||
struct hci_rp_read_page_scan_activity {
|
||||
__u8 status;
|
||||
__le16 interval;
|
||||
__le16 window;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
|
||||
struct hci_cp_write_page_scan_activity {
|
||||
__le16 interval;
|
||||
__le16 window;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_PAGE_SCAN_TYPE 0x0c46
|
||||
struct hci_rp_read_page_scan_type {
|
||||
__u8 status;
|
||||
__u8 type;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
|
||||
#define PAGE_SCAN_TYPE_STANDARD 0x00
|
||||
#define PAGE_SCAN_TYPE_INTERLACED 0x01
|
||||
|
@ -165,6 +165,10 @@ struct hci_dev {
|
||||
__u16 voice_setting;
|
||||
__u8 io_capability;
|
||||
__s8 inq_tx_power;
|
||||
__u16 page_scan_interval;
|
||||
__u16 page_scan_window;
|
||||
__u8 page_scan_type;
|
||||
|
||||
__u16 devid_source;
|
||||
__u16 devid_vendor;
|
||||
__u16 devid_product;
|
||||
@ -248,8 +252,6 @@ struct hci_dev {
|
||||
__u32 req_status;
|
||||
__u32 req_result;
|
||||
|
||||
__u16 init_last_cmd;
|
||||
|
||||
struct list_head mgmt_pending;
|
||||
|
||||
struct discovery_state discovery;
|
||||
@ -574,7 +576,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
|
||||
void hci_disconnect(struct hci_conn *conn, __u8 reason);
|
||||
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
|
||||
void hci_sco_setup(struct hci_conn *conn, __u8 status);
|
||||
|
||||
@ -742,8 +744,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
|
||||
u8 *randomizer);
|
||||
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||
|
||||
int hci_update_ad(struct hci_dev *hdev);
|
||||
|
||||
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
|
||||
int hci_recv_frame(struct sk_buff *skb);
|
||||
@ -1041,6 +1041,22 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
|
||||
int hci_register_cb(struct hci_cb *hcb);
|
||||
int hci_unregister_cb(struct hci_cb *hcb);
|
||||
|
||||
struct hci_request {
|
||||
struct hci_dev *hdev;
|
||||
struct sk_buff_head cmd_q;
|
||||
|
||||
/* If something goes wrong when building the HCI request, the error
|
||||
* value is stored in this field.
|
||||
*/
|
||||
int err;
|
||||
};
|
||||
|
||||
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
|
||||
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
|
||||
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
|
||||
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
|
||||
void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status);
|
||||
|
||||
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
|
||||
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
|
||||
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
|
||||
@ -1153,7 +1169,7 @@ struct hci_sec_filter {
|
||||
#define hci_req_lock(d) mutex_lock(&d->req_lock)
|
||||
#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
|
||||
|
||||
void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
|
||||
void hci_update_ad(struct hci_request *req);
|
||||
|
||||
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
|
||||
u16 latency, u16 to_multiplier);
|
||||
|
@ -158,7 +158,6 @@ struct rfcomm_session {
|
||||
struct timer_list timer;
|
||||
unsigned long state;
|
||||
unsigned long flags;
|
||||
atomic_t refcnt;
|
||||
int initiator;
|
||||
|
||||
/* Default DLC parameters */
|
||||
@ -276,11 +275,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
|
||||
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
|
||||
bdaddr_t *dst);
|
||||
|
||||
static inline void rfcomm_session_hold(struct rfcomm_session *s)
|
||||
{
|
||||
atomic_inc(&s->refcnt);
|
||||
}
|
||||
|
||||
/* ---- RFCOMM sockets ---- */
|
||||
struct sockaddr_rc {
|
||||
sa_family_t rc_family;
|
||||
|
@ -93,9 +93,11 @@ struct device;
|
||||
* enum ieee80211_max_queues - maximum number of queues
|
||||
*
|
||||
* @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
|
||||
* @IEEE80211_MAX_QUEUE_MAP: bitmap with maximum queues set
|
||||
*/
|
||||
enum ieee80211_max_queues {
|
||||
IEEE80211_MAX_QUEUES = 16,
|
||||
IEEE80211_MAX_QUEUE_MAP = BIT(IEEE80211_MAX_QUEUES) - 1,
|
||||
};
|
||||
|
||||
#define IEEE80211_INVAL_HW_QUEUE 0xff
|
||||
@ -1067,6 +1069,9 @@ enum ieee80211_vif_flags {
|
||||
* path needing to access it; even though the netdev carrier will always
|
||||
* be off when it is %NULL there can still be races and packets could be
|
||||
* processed after it switches back to %NULL.
|
||||
* @debugfs_dir: debugfs dentry, can be used by drivers to create own per
|
||||
* interface debug files. Note that it will be NULL for the virtual
|
||||
* monitor interface (if that is requested.)
|
||||
* @drv_priv: data area for driver use, will always be aligned to
|
||||
* sizeof(void *).
|
||||
*/
|
||||
@ -1083,6 +1088,10 @@ struct ieee80211_vif {
|
||||
|
||||
u32 driver_flags;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct dentry *debugfs_dir;
|
||||
#endif
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
@ -1946,14 +1955,14 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
* filter those response frames except in the case of frames that
|
||||
* are buffered in the driver -- those must remain buffered to avoid
|
||||
* reordering. Because it is possible that no frames are released
|
||||
* in this case, the driver must call ieee80211_sta_eosp_irqsafe()
|
||||
* in this case, the driver must call ieee80211_sta_eosp()
|
||||
* to indicate to mac80211 that the service period ended anyway.
|
||||
*
|
||||
* Finally, if frames from multiple TIDs are released from mac80211
|
||||
* but the driver might reorder them, it must clear & set the flags
|
||||
* 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_irqsafe() in this case.
|
||||
* The driver may also use ieee80211_sta_eosp() in this case.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -2226,18 +2235,6 @@ enum ieee80211_roc_type {
|
||||
* MAC address of the device going away.
|
||||
* Hence, this callback must be implemented. It can sleep.
|
||||
*
|
||||
* @add_interface_debugfs: Drivers can use this callback to add debugfs files
|
||||
* when a vif is added to mac80211. This callback and
|
||||
* @remove_interface_debugfs should be within a CONFIG_MAC80211_DEBUGFS
|
||||
* conditional. @remove_interface_debugfs must be provided for cleanup.
|
||||
* This callback can sleep.
|
||||
*
|
||||
* @remove_interface_debugfs: Remove the debugfs files which were added using
|
||||
* @add_interface_debugfs. This callback must remove all debugfs entries
|
||||
* that were added because mac80211 only removes interface debugfs when the
|
||||
* interface is destroyed, not when it is removed from the driver.
|
||||
* This callback can sleep.
|
||||
*
|
||||
* @config: Handler for configuration requests. IEEE 802.11 code calls this
|
||||
* function to change hardware configuration, e.g., channel.
|
||||
* This function should never fail but returns a negative error code
|
||||
@ -2259,6 +2256,9 @@ enum ieee80211_roc_type {
|
||||
* See the section "Frame filtering" for more information.
|
||||
* This callback must be implemented and can sleep.
|
||||
*
|
||||
* @set_multicast_list: Configure the device's interface specific RX multicast
|
||||
* filter. This callback is optional. This callback must be atomic.
|
||||
*
|
||||
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
|
||||
* must be set or cleared for a given STA. Must be atomic.
|
||||
*
|
||||
@ -2440,8 +2440,11 @@ enum ieee80211_roc_type {
|
||||
* @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep.
|
||||
*
|
||||
* @flush: Flush all pending frames from the hardware queue, making sure
|
||||
* that the hardware queues are empty. If the parameter @drop is set
|
||||
* to %true, pending frames may be dropped. The callback can sleep.
|
||||
* that the hardware queues are empty. The @queues parameter is a bitmap
|
||||
* of queues to flush, which is useful if different virtual interfaces
|
||||
* use different hardware queues; it may also indicate all queues.
|
||||
* If the parameter @drop is set to %true, pending frames may be dropped.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @channel_switch: Drivers that need (or want) to offload the channel
|
||||
* switch operation for CSAs received from the AP may implement this
|
||||
@ -2506,7 +2509,7 @@ enum ieee80211_roc_type {
|
||||
* setting the EOSP flag in the QoS header of the frames. Also, when the
|
||||
* service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP
|
||||
* on the last frame in the SP. Alternatively, it may call the function
|
||||
* ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP.
|
||||
* ieee80211_sta_eosp() to inform mac80211 of the end of the SP.
|
||||
* This callback must be atomic.
|
||||
* @allow_buffered_frames: Prepare device to allow the given number of frames
|
||||
* to go out to the given station. The frames will be sent by mac80211
|
||||
@ -2517,7 +2520,7 @@ enum ieee80211_roc_type {
|
||||
* them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag
|
||||
* on the last frame and clear it on all others and also handle the EOSP
|
||||
* bit in the QoS header correctly. Alternatively, it can also call the
|
||||
* ieee80211_sta_eosp_irqsafe() function.
|
||||
* ieee80211_sta_eosp() function.
|
||||
* The @tids parameter is a bitmap and tells the driver which TIDs the
|
||||
* frames will be on; it will at most have two bits set.
|
||||
* This callback must be atomic.
|
||||
@ -2605,6 +2608,10 @@ struct ieee80211_ops {
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast);
|
||||
void (*set_multicast_list)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, bool allmulti,
|
||||
struct netdev_hw_addr_list *mc_list);
|
||||
|
||||
int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set);
|
||||
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
@ -2651,12 +2658,6 @@ struct ieee80211_ops {
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct dentry *dir);
|
||||
void (*add_interface_debugfs)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct dentry *dir);
|
||||
void (*remove_interface_debugfs)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct dentry *dir);
|
||||
#endif
|
||||
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd, struct ieee80211_sta *sta);
|
||||
@ -2691,7 +2692,7 @@ struct ieee80211_ops {
|
||||
struct netlink_callback *cb,
|
||||
void *data, int len);
|
||||
#endif
|
||||
void (*flush)(struct ieee80211_hw *hw, bool drop);
|
||||
void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop);
|
||||
void (*channel_switch)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
int (*napi_poll)(struct ieee80211_hw *hw, int budget);
|
||||
@ -3857,14 +3858,17 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
|
||||
* %IEEE80211_TX_STATUS_EOSP bit and call this function instead.
|
||||
* This applies for PS-Poll as well as uAPSD.
|
||||
*
|
||||
* Note that there is no non-_irqsafe version right now as
|
||||
* it wasn't needed, but just like _tx_status() and _rx()
|
||||
* must not be mixed in irqsafe/non-irqsafe versions, this
|
||||
* function must not be mixed with those either. Use the
|
||||
* all irqsafe, or all non-irqsafe, don't mix! If you need
|
||||
* the non-irqsafe version of this, you need to add it.
|
||||
* Note that just like with _tx_status() and _rx() drivers must
|
||||
* not mix calls to irqsafe/non-irqsafe versions, this function
|
||||
* must not be mixed with those either. Use the all irqsafe, or
|
||||
* all non-irqsafe, don't mix!
|
||||
*
|
||||
* NB: the _irqsafe version of this function doesn't exist, no
|
||||
* driver needs it right now. Don't call this function if
|
||||
* you'd need the _irqsafe version, look at the git history
|
||||
* and restore the _irqsafe version!
|
||||
*/
|
||||
void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta);
|
||||
void ieee80211_sta_eosp(struct ieee80211_sta *pubsta);
|
||||
|
||||
/**
|
||||
* ieee80211_iter_keys - iterate keys programmed into the device
|
||||
|
@ -397,13 +397,12 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||
if (ctrl) {
|
||||
u8 *assoc;
|
||||
|
||||
assoc = kzalloc(assoc_len, GFP_KERNEL);
|
||||
assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL);
|
||||
if (!assoc) {
|
||||
amp_ctrl_put(ctrl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(assoc, rsp->amp_assoc, assoc_len);
|
||||
ctrl->assoc = assoc;
|
||||
ctrl->assoc_len = assoc_len;
|
||||
ctrl->assoc_rem_len = assoc_len;
|
||||
@ -472,13 +471,12 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||
size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
|
||||
u8 *assoc;
|
||||
|
||||
assoc = kzalloc(assoc_len, GFP_KERNEL);
|
||||
assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL);
|
||||
if (!assoc) {
|
||||
amp_ctrl_put(ctrl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(assoc, req->amp_assoc, assoc_len);
|
||||
ctrl->assoc = assoc;
|
||||
ctrl->assoc_len = assoc_len;
|
||||
ctrl->assoc_rem_len = assoc_len;
|
||||
|
@ -92,23 +92,14 @@ int bt_sock_register(int proto, const struct net_proto_family *ops)
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_register);
|
||||
|
||||
int bt_sock_unregister(int proto)
|
||||
void bt_sock_unregister(int proto)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (proto < 0 || proto >= BT_MAX_PROTO)
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
write_lock(&bt_proto_lock);
|
||||
|
||||
if (!bt_proto[proto])
|
||||
err = -ENOENT;
|
||||
else
|
||||
bt_proto[proto] = NULL;
|
||||
|
||||
bt_proto[proto] = NULL;
|
||||
write_unlock(&bt_proto_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_unregister);
|
||||
|
||||
|
@ -253,8 +253,6 @@ error:
|
||||
void __exit bnep_sock_cleanup(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "bnep");
|
||||
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
|
||||
BT_ERR("Can't unregister BNEP socket");
|
||||
|
||||
bt_sock_unregister(BTPROTO_BNEP);
|
||||
proto_unregister(&bnep_proto);
|
||||
}
|
||||
|
@ -264,8 +264,6 @@ error:
|
||||
void cmtp_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "cmtp");
|
||||
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
|
||||
BT_ERR("Can't unregister CMTP socket");
|
||||
|
||||
bt_sock_unregister(BTPROTO_CMTP);
|
||||
proto_unregister(&cmtp_proto);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn)
|
||||
hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
|
||||
void hci_disconnect(struct hci_conn *conn, __u8 reason)
|
||||
{
|
||||
struct hci_cp_disconnect cp;
|
||||
|
||||
@ -253,7 +253,7 @@ static void hci_conn_disconnect(struct hci_conn *conn)
|
||||
hci_amp_disconn(conn, reason);
|
||||
break;
|
||||
default:
|
||||
hci_acl_disconn(conn, reason);
|
||||
hci_disconnect(conn, reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,7 +53,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
|
||||
hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
|
||||
|
||||
hci_conn_check_pending(hdev);
|
||||
}
|
||||
@ -183,8 +183,6 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
|
||||
|
||||
if (!status)
|
||||
hdev->link_policy = get_unaligned_le16(sent);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status);
|
||||
}
|
||||
|
||||
static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -195,11 +193,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
clear_bit(HCI_RESET, &hdev->flags);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_RESET, status);
|
||||
|
||||
/* Reset all non-persistent flags */
|
||||
hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
|
||||
BIT(HCI_PERIODIC_INQ));
|
||||
hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
|
||||
|
||||
hdev->discovery.state = DISCOVERY_STOPPED;
|
||||
hdev->inq_tx_power = HCI_TX_POWER_INVALID;
|
||||
@ -228,11 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (!status && !test_bit(HCI_INIT, &hdev->flags))
|
||||
hci_update_ad(hdev);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -270,8 +260,6 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
mgmt_auth_enable_complete(hdev, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -293,8 +281,6 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
else
|
||||
clear_bit(HCI_ENCRYPT, &hdev->flags);
|
||||
}
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -343,7 +329,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
done:
|
||||
hci_dev_unlock(hdev);
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
|
||||
}
|
||||
|
||||
static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -435,15 +420,6 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev,
|
||||
hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
|
||||
}
|
||||
|
||||
static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
@ -472,211 +448,6 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
|
||||
{
|
||||
if (lmp_ext_inq_capable(hdev))
|
||||
return 2;
|
||||
|
||||
if (lmp_inq_rssi_capable(hdev))
|
||||
return 1;
|
||||
|
||||
if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
|
||||
hdev->lmp_subver == 0x0757)
|
||||
return 1;
|
||||
|
||||
if (hdev->manufacturer == 15) {
|
||||
if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963)
|
||||
return 1;
|
||||
if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963)
|
||||
return 1;
|
||||
if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 &&
|
||||
hdev->lmp_subver == 0x1805)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hci_setup_inquiry_mode(struct hci_dev *hdev)
|
||||
{
|
||||
u8 mode;
|
||||
|
||||
mode = hci_get_inquiry_mode(hdev);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode);
|
||||
}
|
||||
|
||||
static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||
{
|
||||
/* The second byte is 0xff instead of 0x9f (two reserved bits
|
||||
* disabled) since a Broadcom 1.2 dongle doesn't respond to the
|
||||
* command otherwise */
|
||||
u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
/* CSR 1.1 dongles does not accept any bitfield so don't try to set
|
||||
* any event mask for pre 1.2 devices */
|
||||
if (hdev->hci_ver < BLUETOOTH_VER_1_2)
|
||||
return;
|
||||
|
||||
if (lmp_bredr_capable(hdev)) {
|
||||
events[4] |= 0x01; /* Flow Specification Complete */
|
||||
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
||||
events[4] |= 0x04; /* Read Remote Extended Features Complete */
|
||||
events[5] |= 0x08; /* Synchronous Connection Complete */
|
||||
events[5] |= 0x10; /* Synchronous Connection Changed */
|
||||
}
|
||||
|
||||
if (lmp_inq_rssi_capable(hdev))
|
||||
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
||||
|
||||
if (lmp_sniffsubr_capable(hdev))
|
||||
events[5] |= 0x20; /* Sniff Subrating */
|
||||
|
||||
if (lmp_pause_enc_capable(hdev))
|
||||
events[5] |= 0x80; /* Encryption Key Refresh Complete */
|
||||
|
||||
if (lmp_ext_inq_capable(hdev))
|
||||
events[5] |= 0x40; /* Extended Inquiry Result */
|
||||
|
||||
if (lmp_no_flush_capable(hdev))
|
||||
events[7] |= 0x01; /* Enhanced Flush Complete */
|
||||
|
||||
if (lmp_lsto_capable(hdev))
|
||||
events[6] |= 0x80; /* Link Supervision Timeout Changed */
|
||||
|
||||
if (lmp_ssp_capable(hdev)) {
|
||||
events[6] |= 0x01; /* IO Capability Request */
|
||||
events[6] |= 0x02; /* IO Capability Response */
|
||||
events[6] |= 0x04; /* User Confirmation Request */
|
||||
events[6] |= 0x08; /* User Passkey Request */
|
||||
events[6] |= 0x10; /* Remote OOB Data Request */
|
||||
events[6] |= 0x20; /* Simple Pairing Complete */
|
||||
events[7] |= 0x04; /* User Passkey Notification */
|
||||
events[7] |= 0x08; /* Keypress Notification */
|
||||
events[7] |= 0x10; /* Remote Host Supported
|
||||
* Features Notification */
|
||||
}
|
||||
|
||||
if (lmp_le_capable(hdev))
|
||||
events[7] |= 0x20; /* LE Meta-Event */
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
|
||||
|
||||
if (lmp_le_capable(hdev)) {
|
||||
memset(events, 0, sizeof(events));
|
||||
events[0] = 0x1f;
|
||||
hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
|
||||
sizeof(events), events);
|
||||
}
|
||||
}
|
||||
|
||||
static void bredr_setup(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_cp_delete_stored_link_key cp;
|
||||
__le16 param;
|
||||
__u8 flt_type;
|
||||
|
||||
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
|
||||
|
||||
/* Read Class of Device */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
|
||||
|
||||
/* Read Local Name */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
|
||||
|
||||
/* Read Voice Setting */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
|
||||
|
||||
/* Clear Event Filters */
|
||||
flt_type = HCI_FLT_CLEAR_ALL;
|
||||
hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
|
||||
|
||||
/* Connection accept timeout ~20 secs */
|
||||
param = __constant_cpu_to_le16(0x7d00);
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
|
||||
|
||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||
cp.delete_all = 1;
|
||||
hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
static void le_setup(struct hci_dev *hdev)
|
||||
{
|
||||
/* Read LE Buffer Size */
|
||||
hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
|
||||
|
||||
/* Read LE Local Supported Features */
|
||||
hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL);
|
||||
|
||||
/* Read LE Advertising Channel TX Power */
|
||||
hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
||||
|
||||
/* Read LE White List Size */
|
||||
hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
|
||||
|
||||
/* Read LE Supported States */
|
||||
hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
|
||||
}
|
||||
|
||||
static void hci_setup(struct hci_dev *hdev)
|
||||
{
|
||||
if (hdev->dev_type != HCI_BREDR)
|
||||
return;
|
||||
|
||||
/* Read BD Address */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
|
||||
|
||||
if (lmp_bredr_capable(hdev))
|
||||
bredr_setup(hdev);
|
||||
|
||||
if (lmp_le_capable(hdev))
|
||||
le_setup(hdev);
|
||||
|
||||
hci_setup_event_mask(hdev);
|
||||
|
||||
if (hdev->hci_ver > BLUETOOTH_VER_1_1)
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
|
||||
|
||||
if (lmp_ssp_capable(hdev)) {
|
||||
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
|
||||
u8 mode = 0x01;
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
|
||||
sizeof(mode), &mode);
|
||||
} else {
|
||||
struct hci_cp_write_eir cp;
|
||||
|
||||
memset(hdev->eir, 0, sizeof(hdev->eir));
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
|
||||
}
|
||||
}
|
||||
|
||||
if (lmp_inq_rssi_capable(hdev))
|
||||
hci_setup_inquiry_mode(hdev);
|
||||
|
||||
if (lmp_inq_tx_pwr_capable(hdev))
|
||||
hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
|
||||
|
||||
if (lmp_ext_feat_capable(hdev)) {
|
||||
struct hci_cp_read_local_ext_features cp;
|
||||
|
||||
cp.page = 0x01;
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp),
|
||||
&cp);
|
||||
}
|
||||
|
||||
if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
|
||||
u8 enable = 1;
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable),
|
||||
&enable);
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_read_local_version *rp = (void *) skb->data;
|
||||
@ -684,7 +455,7 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
goto done;
|
||||
return;
|
||||
|
||||
hdev->hci_ver = rp->hci_ver;
|
||||
hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
|
||||
@ -694,30 +465,6 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name,
|
||||
hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
|
||||
|
||||
if (test_bit(HCI_INIT, &hdev->flags))
|
||||
hci_setup(hdev);
|
||||
|
||||
done:
|
||||
hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status);
|
||||
}
|
||||
|
||||
static void hci_setup_link_policy(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_cp_write_def_link_policy cp;
|
||||
u16 link_policy = 0;
|
||||
|
||||
if (lmp_rswitch_capable(hdev))
|
||||
link_policy |= HCI_LP_RSWITCH;
|
||||
if (lmp_hold_capable(hdev))
|
||||
link_policy |= HCI_LP_HOLD;
|
||||
if (lmp_sniff_capable(hdev))
|
||||
link_policy |= HCI_LP_SNIFF;
|
||||
if (lmp_park_capable(hdev))
|
||||
link_policy |= HCI_LP_PARK;
|
||||
|
||||
cp.policy = cpu_to_le16(link_policy);
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_commands(struct hci_dev *hdev,
|
||||
@ -727,16 +474,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
goto done;
|
||||
|
||||
memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
|
||||
|
||||
if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10))
|
||||
hci_setup_link_policy(hdev);
|
||||
|
||||
done:
|
||||
hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status);
|
||||
if (!rp->status)
|
||||
memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_features(struct hci_dev *hdev,
|
||||
@ -795,22 +534,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
|
||||
hdev->features[6], hdev->features[7]);
|
||||
}
|
||||
|
||||
static void hci_set_le_support(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_cp_write_le_host_supported cp;
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
|
||||
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
|
||||
cp.le = 1;
|
||||
cp.simul = lmp_le_br_capable(hdev);
|
||||
}
|
||||
|
||||
if (cp.le != lmp_host_le_capable(hdev))
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
|
||||
&cp);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -819,7 +542,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
goto done;
|
||||
return;
|
||||
|
||||
switch (rp->page) {
|
||||
case 0:
|
||||
@ -829,12 +552,6 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
|
||||
memcpy(hdev->host_features, rp->features, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
|
||||
hci_set_le_support(hdev);
|
||||
|
||||
done:
|
||||
hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
|
||||
@ -844,12 +561,8 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
hdev->flow_ctl_mode = rp->mode;
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status);
|
||||
if (!rp->status)
|
||||
hdev->flow_ctl_mode = rp->mode;
|
||||
}
|
||||
|
||||
static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -886,8 +599,65 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
if (!rp->status)
|
||||
bacpy(&hdev->bdaddr, &rp->bdaddr);
|
||||
}
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
|
||||
static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
|
||||
hdev->page_scan_interval = __le16_to_cpu(rp->interval);
|
||||
hdev->page_scan_window = __le16_to_cpu(rp->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u8 status = *((u8 *) skb->data);
|
||||
struct hci_cp_write_page_scan_activity *sent;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
|
||||
if (!sent)
|
||||
return;
|
||||
|
||||
hdev->page_scan_interval = __le16_to_cpu(sent->interval);
|
||||
hdev->page_scan_window = __le16_to_cpu(sent->window);
|
||||
}
|
||||
|
||||
static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
|
||||
hdev->page_scan_type = rp->type;
|
||||
}
|
||||
|
||||
static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u8 status = *((u8 *) skb->data);
|
||||
u8 *type;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
|
||||
if (type)
|
||||
hdev->page_scan_type = *type;
|
||||
}
|
||||
|
||||
static void hci_cc_read_data_block_size(struct hci_dev *hdev,
|
||||
@ -908,17 +678,6 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev,
|
||||
|
||||
BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
|
||||
hdev->block_cnt, hdev->block_len);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
|
||||
@ -942,8 +701,6 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
|
||||
hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
|
||||
hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
|
||||
|
||||
a2mp_rsp:
|
||||
a2mp_send_getinfo_rsp(hdev);
|
||||
}
|
||||
@ -985,35 +742,6 @@ a2mp_rsp:
|
||||
a2mp_send_create_phy_link_req(hdev, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status);
|
||||
}
|
||||
|
||||
static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status);
|
||||
}
|
||||
|
||||
static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -1023,17 +751,6 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
|
||||
|
||||
if (!rp->status)
|
||||
hdev->inq_tx_power = rp->tx_power;
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status);
|
||||
}
|
||||
|
||||
static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -1095,8 +812,6 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
|
||||
hdev->le_cnt = hdev->le_pkts;
|
||||
|
||||
BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_read_local_features(struct hci_dev *hdev,
|
||||
@ -1108,8 +823,6 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev,
|
||||
|
||||
if (!rp->status)
|
||||
memcpy(hdev->le_features, rp->features, 8);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
|
||||
@ -1119,22 +832,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (!rp->status) {
|
||||
if (!rp->status)
|
||||
hdev->adv_tx_power = rp->tx_power;
|
||||
if (!test_bit(HCI_INIT, &hdev->flags))
|
||||
hci_update_ad(hdev);
|
||||
}
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
|
||||
}
|
||||
|
||||
static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -1231,12 +930,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
|
||||
}
|
||||
|
||||
if (!test_bit(HCI_INIT, &hdev->flags)) {
|
||||
struct hci_request req;
|
||||
|
||||
hci_req_init(&req, hdev);
|
||||
hci_update_ad(&req);
|
||||
hci_req_run(&req, NULL);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (!test_bit(HCI_INIT, &hdev->flags))
|
||||
hci_update_ad(hdev);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -1245,8 +947,6 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
|
||||
|
||||
if (status) {
|
||||
hci_dev_lock(hdev);
|
||||
mgmt_start_discovery_failed(hdev, status);
|
||||
@ -1269,8 +969,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
|
||||
|
||||
switch (cp->enable) {
|
||||
case LE_SCANNING_ENABLED:
|
||||
hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
|
||||
|
||||
if (status) {
|
||||
hci_dev_lock(hdev);
|
||||
mgmt_start_discovery_failed(hdev, status);
|
||||
@ -1321,32 +1019,6 @@ static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
|
||||
|
||||
if (!rp->status)
|
||||
hdev->le_white_list_size = rp->size;
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
|
||||
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
|
||||
@ -1358,8 +1030,6 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
|
||||
|
||||
if (!rp->status)
|
||||
memcpy(hdev->le_states, rp->le_states, 8);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
|
||||
@ -1389,8 +1059,6 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
|
||||
!test_bit(HCI_INIT, &hdev->flags))
|
||||
mgmt_le_enable_complete(hdev, sent->le, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
|
||||
}
|
||||
|
||||
static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
|
||||
@ -1412,7 +1080,6 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
if (status) {
|
||||
hci_req_complete(hdev, HCI_OP_INQUIRY, status);
|
||||
hci_conn_check_pending(hdev);
|
||||
hci_dev_lock(hdev);
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
@ -1884,11 +1551,6 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
|
||||
{
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
}
|
||||
|
||||
static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
|
||||
{
|
||||
struct hci_cp_create_phy_link *cp;
|
||||
@ -1930,11 +1592,6 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
|
||||
amp_write_remote_assoc(hdev, cp->phy_handle);
|
||||
}
|
||||
|
||||
static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status)
|
||||
{
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
}
|
||||
|
||||
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
@ -1943,7 +1600,7 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_INQUIRY, status);
|
||||
hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
|
||||
|
||||
hci_conn_check_pending(hdev);
|
||||
|
||||
@ -2399,7 +2056,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
|
||||
if (ev->status && conn->state == BT_CONNECTED) {
|
||||
hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
hci_conn_put(conn);
|
||||
goto unlock;
|
||||
}
|
||||
@ -2491,20 +2148,10 @@ unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
BT_DBG("%s", hdev->name);
|
||||
}
|
||||
|
||||
static void hci_qos_setup_complete_evt(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
BT_DBG("%s", hdev->name);
|
||||
}
|
||||
|
||||
static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_cmd_complete *ev = (void *) skb->data;
|
||||
u8 status = skb->data[sizeof(*ev)];
|
||||
__u16 opcode;
|
||||
|
||||
skb_pull(skb, sizeof(*ev));
|
||||
@ -2588,10 +2235,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_write_voice_setting(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_HOST_BUFFER_SIZE:
|
||||
hci_cc_host_buffer_size(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_SSP_MODE:
|
||||
hci_cc_write_ssp_mode(hdev, skb);
|
||||
break;
|
||||
@ -2620,12 +2263,24 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_read_bd_addr(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_DATA_BLOCK_SIZE:
|
||||
hci_cc_read_data_block_size(hdev, skb);
|
||||
case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
|
||||
hci_cc_read_page_scan_activity(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_CA_TIMEOUT:
|
||||
hci_cc_write_ca_timeout(hdev, skb);
|
||||
case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
|
||||
hci_cc_write_page_scan_activity(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_PAGE_SCAN_TYPE:
|
||||
hci_cc_read_page_scan_type(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_PAGE_SCAN_TYPE:
|
||||
hci_cc_write_page_scan_type(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_DATA_BLOCK_SIZE:
|
||||
hci_cc_read_data_block_size(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_FLOW_CONTROL_MODE:
|
||||
@ -2640,26 +2295,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_read_local_amp_assoc(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_DELETE_STORED_LINK_KEY:
|
||||
hci_cc_delete_stored_link_key(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_SET_EVENT_MASK:
|
||||
hci_cc_set_event_mask(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_WRITE_INQUIRY_MODE:
|
||||
hci_cc_write_inquiry_mode(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_INQ_RSP_TX_POWER:
|
||||
hci_cc_read_inq_rsp_tx_power(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_SET_EVENT_FLT:
|
||||
hci_cc_set_event_flt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_PIN_CODE_REPLY:
|
||||
hci_cc_pin_code_reply(hdev, skb);
|
||||
break;
|
||||
@ -2684,10 +2323,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_le_read_adv_tx_power(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_SET_EVENT_MASK:
|
||||
hci_cc_le_set_event_mask(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_USER_CONFIRM_REPLY:
|
||||
hci_cc_user_confirm_reply(hdev, skb);
|
||||
break;
|
||||
@ -2720,14 +2355,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cc_le_read_white_list_size(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_LTK_REPLY:
|
||||
hci_cc_le_ltk_reply(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_LTK_NEG_REPLY:
|
||||
hci_cc_le_ltk_neg_reply(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_READ_SUPPORTED_STATES:
|
||||
hci_cc_le_read_supported_states(hdev, skb);
|
||||
break;
|
||||
@ -2745,9 +2372,11 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ev->opcode != HCI_OP_NOP)
|
||||
if (opcode != HCI_OP_NOP)
|
||||
del_timer(&hdev->cmd_timer);
|
||||
|
||||
hci_req_cmd_complete(hdev, opcode, status);
|
||||
|
||||
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
|
||||
atomic_set(&hdev->cmd_cnt, 1);
|
||||
if (!skb_queue_empty(&hdev->cmd_q))
|
||||
@ -2817,10 +2446,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cs_le_create_conn(hdev, ev->status);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_START_ENC:
|
||||
hci_cs_le_start_enc(hdev, ev->status);
|
||||
break;
|
||||
|
||||
case HCI_OP_CREATE_PHY_LINK:
|
||||
hci_cs_create_phylink(hdev, ev->status);
|
||||
break;
|
||||
@ -2829,18 +2454,16 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_cs_accept_phylink(hdev, ev->status);
|
||||
break;
|
||||
|
||||
case HCI_OP_CREATE_LOGICAL_LINK:
|
||||
hci_cs_create_logical_link(hdev, ev->status);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ev->opcode != HCI_OP_NOP)
|
||||
if (opcode != HCI_OP_NOP)
|
||||
del_timer(&hdev->cmd_timer);
|
||||
|
||||
hci_req_cmd_status(hdev, opcode, ev->status);
|
||||
|
||||
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
|
||||
atomic_set(&hdev->cmd_cnt, 1);
|
||||
if (!skb_queue_empty(&hdev->cmd_q))
|
||||
@ -3391,18 +3014,6 @@ unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
BT_DBG("%s", hdev->name);
|
||||
}
|
||||
|
||||
static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_sniff_subrate *ev = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
|
||||
}
|
||||
|
||||
static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -3472,7 +3083,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
|
||||
if (ev->status && conn->state == BT_CONNECTED) {
|
||||
hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
hci_conn_put(conn);
|
||||
goto unlock;
|
||||
}
|
||||
@ -4130,14 +3741,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_remote_features_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_REMOTE_VERSION:
|
||||
hci_remote_version_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_QOS_SETUP_COMPLETE:
|
||||
hci_qos_setup_complete_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_CMD_COMPLETE:
|
||||
hci_cmd_complete_evt(hdev, skb);
|
||||
break;
|
||||
@ -4194,14 +3797,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_sync_conn_complete_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_SYNC_CONN_CHANGED:
|
||||
hci_sync_conn_changed_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_SNIFF_SUBRATE:
|
||||
hci_sniff_subrate_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_EXTENDED_INQUIRY_RESULT:
|
||||
hci_extended_inquiry_result_evt(hdev, skb);
|
||||
break;
|
||||
|
@ -854,6 +854,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
skb_queue_tail(&hdev->raw_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
} else {
|
||||
/* Stand-alone HCI commands must be flaged as
|
||||
* single-command requests.
|
||||
*/
|
||||
bt_cb(skb)->req.start = true;
|
||||
|
||||
skb_queue_tail(&hdev->cmd_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->cmd_work);
|
||||
}
|
||||
@ -1121,8 +1126,6 @@ error:
|
||||
void hci_sock_cleanup(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "hci");
|
||||
if (bt_sock_unregister(BTPROTO_HCI) < 0)
|
||||
BT_ERR("HCI socket unregistration failed");
|
||||
|
||||
bt_sock_unregister(BTPROTO_HCI);
|
||||
proto_unregister(&hci_sk_proto);
|
||||
}
|
||||
|
@ -590,10 +590,8 @@ int __init bt_sysfs_init(void)
|
||||
bt_debugfs = debugfs_create_dir("bluetooth", NULL);
|
||||
|
||||
bt_class = class_create(THIS_MODULE, "bluetooth");
|
||||
if (IS_ERR(bt_class))
|
||||
return PTR_ERR(bt_class);
|
||||
|
||||
return 0;
|
||||
return PTR_RET(bt_class);
|
||||
}
|
||||
|
||||
void bt_sysfs_cleanup(void)
|
||||
|
@ -311,6 +311,9 @@ static int hidp_get_raw_report(struct hid_device *hid,
|
||||
int numbered_reports = hid->report_enum[report_type].numbered;
|
||||
int ret;
|
||||
|
||||
if (atomic_read(&session->terminate))
|
||||
return -EIO;
|
||||
|
||||
switch (report_type) {
|
||||
case HID_FEATURE_REPORT:
|
||||
report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
|
||||
@ -722,6 +725,7 @@ static int hidp_session(void *arg)
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
set_current_state(TASK_RUNNING);
|
||||
atomic_inc(&session->terminate);
|
||||
remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
|
||||
remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
|
||||
|
||||
|
@ -304,8 +304,6 @@ error:
|
||||
void __exit hidp_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "hidp");
|
||||
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
|
||||
BT_ERR("Can't unregister HIDP socket");
|
||||
|
||||
bt_sock_unregister(BTPROTO_HIDP);
|
||||
proto_unregister(&hidp_proto);
|
||||
}
|
||||
|
@ -1312,8 +1312,6 @@ error:
|
||||
void l2cap_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "l2cap");
|
||||
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
|
||||
BT_ERR("L2CAP socket unregistration failed");
|
||||
|
||||
bt_sock_unregister(BTPROTO_L2CAP);
|
||||
proto_unregister(&l2cap_proto);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -69,7 +69,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
||||
u8 sec_level,
|
||||
int *err);
|
||||
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
|
||||
static void rfcomm_session_del(struct rfcomm_session *s);
|
||||
static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
|
||||
|
||||
/* ---- RFCOMM frame parsing macros ---- */
|
||||
#define __get_dlci(b) ((b & 0xfc) >> 2)
|
||||
@ -108,12 +108,6 @@ static void rfcomm_schedule(void)
|
||||
wake_up_process(rfcomm_thread);
|
||||
}
|
||||
|
||||
static void rfcomm_session_put(struct rfcomm_session *s)
|
||||
{
|
||||
if (atomic_dec_and_test(&s->refcnt))
|
||||
rfcomm_session_del(s);
|
||||
}
|
||||
|
||||
/* ---- RFCOMM FCS computation ---- */
|
||||
|
||||
/* reversed, 8-bit, poly=0x07 */
|
||||
@ -249,16 +243,14 @@ static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout)
|
||||
{
|
||||
BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout);
|
||||
|
||||
if (!mod_timer(&s->timer, jiffies + timeout))
|
||||
rfcomm_session_hold(s);
|
||||
mod_timer(&s->timer, jiffies + timeout);
|
||||
}
|
||||
|
||||
static void rfcomm_session_clear_timer(struct rfcomm_session *s)
|
||||
{
|
||||
BT_DBG("session %p state %ld", s, s->state);
|
||||
|
||||
if (del_timer(&s->timer))
|
||||
rfcomm_session_put(s);
|
||||
del_timer_sync(&s->timer);
|
||||
}
|
||||
|
||||
/* ---- RFCOMM DLCs ---- */
|
||||
@ -336,8 +328,6 @@ static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d)
|
||||
{
|
||||
BT_DBG("dlc %p session %p", d, s);
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
rfcomm_session_clear_timer(s);
|
||||
rfcomm_dlc_hold(d);
|
||||
list_add(&d->list, &s->dlcs);
|
||||
@ -356,8 +346,6 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
|
||||
|
||||
if (list_empty(&s->dlcs))
|
||||
rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT);
|
||||
|
||||
rfcomm_session_put(s);
|
||||
}
|
||||
|
||||
static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
|
||||
@ -493,12 +481,34 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
|
||||
|
||||
int rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
|
||||
{
|
||||
int r;
|
||||
int r = 0;
|
||||
struct rfcomm_dlc *d_list;
|
||||
struct rfcomm_session *s, *s_list;
|
||||
|
||||
BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err);
|
||||
|
||||
rfcomm_lock();
|
||||
|
||||
r = __rfcomm_dlc_close(d, err);
|
||||
s = d->session;
|
||||
if (!s)
|
||||
goto no_session;
|
||||
|
||||
/* after waiting on the mutex check the session still exists
|
||||
* then check the dlc still exists
|
||||
*/
|
||||
list_for_each_entry(s_list, &session_list, list) {
|
||||
if (s_list == s) {
|
||||
list_for_each_entry(d_list, &s->dlcs, list) {
|
||||
if (d_list == d) {
|
||||
r = __rfcomm_dlc_close(d, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
no_session:
|
||||
rfcomm_unlock();
|
||||
return r;
|
||||
}
|
||||
@ -609,7 +619,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rfcomm_session_del(struct rfcomm_session *s)
|
||||
static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s)
|
||||
{
|
||||
int state = s->state;
|
||||
|
||||
@ -617,15 +627,14 @@ static void rfcomm_session_del(struct rfcomm_session *s)
|
||||
|
||||
list_del(&s->list);
|
||||
|
||||
if (state == BT_CONNECTED)
|
||||
rfcomm_send_disc(s, 0);
|
||||
|
||||
rfcomm_session_clear_timer(s);
|
||||
sock_release(s->sock);
|
||||
kfree(s);
|
||||
|
||||
if (state != BT_LISTEN)
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
|
||||
@ -644,17 +653,16 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rfcomm_session_close(struct rfcomm_session *s, int err)
|
||||
static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s,
|
||||
int err)
|
||||
{
|
||||
struct rfcomm_dlc *d;
|
||||
struct list_head *p, *n;
|
||||
|
||||
BT_DBG("session %p state %ld err %d", s, s->state, err);
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
s->state = BT_CLOSED;
|
||||
|
||||
BT_DBG("session %p state %ld err %d", s, s->state, err);
|
||||
|
||||
/* Close all dlcs */
|
||||
list_for_each_safe(p, n, &s->dlcs) {
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
@ -663,7 +671,7 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
|
||||
}
|
||||
|
||||
rfcomm_session_clear_timer(s);
|
||||
rfcomm_session_put(s);
|
||||
return rfcomm_session_del(s);
|
||||
}
|
||||
|
||||
static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
||||
@ -715,8 +723,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
||||
if (*err == 0 || *err == -EINPROGRESS)
|
||||
return s;
|
||||
|
||||
rfcomm_session_del(s);
|
||||
return NULL;
|
||||
return rfcomm_session_del(s);
|
||||
|
||||
failed:
|
||||
sock_release(sock);
|
||||
@ -1105,7 +1112,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
|
||||
}
|
||||
|
||||
/* ---- RFCOMM frame reception ---- */
|
||||
static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
{
|
||||
BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
|
||||
|
||||
@ -1114,7 +1121,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
|
||||
if (!d) {
|
||||
rfcomm_send_dm(s, dlci);
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
switch (d->state) {
|
||||
@ -1150,25 +1157,14 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
break;
|
||||
|
||||
case BT_DISCONN:
|
||||
/* rfcomm_session_put is called later so don't do
|
||||
* anything here otherwise we will mess up the session
|
||||
* reference counter:
|
||||
*
|
||||
* (a) when we are the initiator dlc_unlink will drive
|
||||
* the reference counter to 0 (there is no initial put
|
||||
* after session_add)
|
||||
*
|
||||
* (b) when we are not the initiator rfcomm_rx_process
|
||||
* will explicitly call put to balance the initial hold
|
||||
* done after session add.
|
||||
*/
|
||||
s = rfcomm_session_close(s, ECONNRESET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
|
||||
static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@ -1192,13 +1188,13 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
|
||||
else
|
||||
err = ECONNRESET;
|
||||
|
||||
s->state = BT_CLOSED;
|
||||
rfcomm_session_close(s, err);
|
||||
s = rfcomm_session_close(s, err);
|
||||
}
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
|
||||
static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s,
|
||||
u8 dlci)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@ -1227,11 +1223,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
|
||||
else
|
||||
err = ECONNRESET;
|
||||
|
||||
s->state = BT_CLOSED;
|
||||
rfcomm_session_close(s, err);
|
||||
s = rfcomm_session_close(s, err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
void rfcomm_dlc_accept(struct rfcomm_dlc *d)
|
||||
@ -1652,11 +1646,18 @@ drop:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rfcomm_hdr *hdr = (void *) skb->data;
|
||||
u8 type, dlci, fcs;
|
||||
|
||||
if (!s) {
|
||||
/* no session, so free socket data */
|
||||
kfree_skb(skb);
|
||||
return s;
|
||||
}
|
||||
|
||||
dlci = __get_dlci(hdr->addr);
|
||||
type = __get_type(hdr->ctrl);
|
||||
|
||||
@ -1667,7 +1668,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
if (__check_fcs(skb->data, type, fcs)) {
|
||||
BT_ERR("bad checksum in packet");
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
return s;
|
||||
}
|
||||
|
||||
if (__test_ea(hdr->len))
|
||||
@ -1683,22 +1684,23 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
|
||||
case RFCOMM_DISC:
|
||||
if (__test_pf(hdr->ctrl))
|
||||
rfcomm_recv_disc(s, dlci);
|
||||
s = rfcomm_recv_disc(s, dlci);
|
||||
break;
|
||||
|
||||
case RFCOMM_UA:
|
||||
if (__test_pf(hdr->ctrl))
|
||||
rfcomm_recv_ua(s, dlci);
|
||||
s = rfcomm_recv_ua(s, dlci);
|
||||
break;
|
||||
|
||||
case RFCOMM_DM:
|
||||
rfcomm_recv_dm(s, dlci);
|
||||
s = rfcomm_recv_dm(s, dlci);
|
||||
break;
|
||||
|
||||
case RFCOMM_UIH:
|
||||
if (dlci)
|
||||
return rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
|
||||
|
||||
if (dlci) {
|
||||
rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
|
||||
return s;
|
||||
}
|
||||
rfcomm_recv_mcc(s, skb);
|
||||
break;
|
||||
|
||||
@ -1707,7 +1709,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ---- Connection and data processing ---- */
|
||||
@ -1844,7 +1846,7 @@ static void rfcomm_process_dlcs(struct rfcomm_session *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void rfcomm_process_rx(struct rfcomm_session *s)
|
||||
static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s)
|
||||
{
|
||||
struct socket *sock = s->sock;
|
||||
struct sock *sk = sock->sk;
|
||||
@ -1856,17 +1858,15 @@ static void rfcomm_process_rx(struct rfcomm_session *s)
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
|
||||
skb_orphan(skb);
|
||||
if (!skb_linearize(skb))
|
||||
rfcomm_recv_frame(s, skb);
|
||||
s = rfcomm_recv_frame(s, skb);
|
||||
else
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
if (sk->sk_state == BT_CLOSED) {
|
||||
if (!s->initiator)
|
||||
rfcomm_session_put(s);
|
||||
if (s && (sk->sk_state == BT_CLOSED))
|
||||
s = rfcomm_session_close(s, sk->sk_err);
|
||||
|
||||
rfcomm_session_close(s, sk->sk_err);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rfcomm_accept_connection(struct rfcomm_session *s)
|
||||
@ -1891,8 +1891,6 @@ static void rfcomm_accept_connection(struct rfcomm_session *s)
|
||||
|
||||
s = rfcomm_session_add(nsock, BT_OPEN);
|
||||
if (s) {
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
/* We should adjust MTU on incoming sessions.
|
||||
* L2CAP MTU minus UIH header and FCS. */
|
||||
s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
|
||||
@ -1903,7 +1901,7 @@ static void rfcomm_accept_connection(struct rfcomm_session *s)
|
||||
sock_release(nsock);
|
||||
}
|
||||
|
||||
static void rfcomm_check_connection(struct rfcomm_session *s)
|
||||
static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s)
|
||||
{
|
||||
struct sock *sk = s->sock->sk;
|
||||
|
||||
@ -1921,10 +1919,10 @@ static void rfcomm_check_connection(struct rfcomm_session *s)
|
||||
break;
|
||||
|
||||
case BT_CLOSED:
|
||||
s->state = BT_CLOSED;
|
||||
rfcomm_session_close(s, sk->sk_err);
|
||||
s = rfcomm_session_close(s, sk->sk_err);
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rfcomm_process_sessions(void)
|
||||
@ -1940,7 +1938,6 @@ static void rfcomm_process_sessions(void)
|
||||
if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
|
||||
s->state = BT_DISCONN;
|
||||
rfcomm_send_disc(s, 0);
|
||||
rfcomm_session_put(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1949,21 +1946,18 @@ static void rfcomm_process_sessions(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
switch (s->state) {
|
||||
case BT_BOUND:
|
||||
rfcomm_check_connection(s);
|
||||
s = rfcomm_check_connection(s);
|
||||
break;
|
||||
|
||||
default:
|
||||
rfcomm_process_rx(s);
|
||||
s = rfcomm_process_rx(s);
|
||||
break;
|
||||
}
|
||||
|
||||
rfcomm_process_dlcs(s);
|
||||
|
||||
rfcomm_session_put(s);
|
||||
if (s)
|
||||
rfcomm_process_dlcs(s);
|
||||
}
|
||||
|
||||
rfcomm_unlock();
|
||||
@ -2010,10 +2004,11 @@ static int rfcomm_add_listener(bdaddr_t *ba)
|
||||
|
||||
/* Add listening session */
|
||||
s = rfcomm_session_add(sock, BT_LISTEN);
|
||||
if (!s)
|
||||
if (!s) {
|
||||
err = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
return 0;
|
||||
failed:
|
||||
sock_release(sock);
|
||||
@ -2071,8 +2066,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
list_for_each_safe(p, n, &s->dlcs) {
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
|
||||
@ -2104,8 +2097,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
||||
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
|
||||
}
|
||||
|
||||
rfcomm_session_put(s);
|
||||
|
||||
rfcomm_schedule();
|
||||
}
|
||||
|
||||
|
@ -1065,8 +1065,7 @@ void __exit rfcomm_cleanup_sockets(void)
|
||||
|
||||
debugfs_remove(rfcomm_sock_debugfs);
|
||||
|
||||
if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
|
||||
BT_ERR("RFCOMM socket layer unregistration failed");
|
||||
bt_sock_unregister(BTPROTO_RFCOMM);
|
||||
|
||||
proto_unregister(&rfcomm_proto);
|
||||
}
|
||||
|
@ -1111,8 +1111,7 @@ void __exit sco_exit(void)
|
||||
|
||||
debugfs_remove(sco_debugfs);
|
||||
|
||||
if (bt_sock_unregister(BTPROTO_SCO) < 0)
|
||||
BT_ERR("SCO socket unregistration failed");
|
||||
bt_sock_unregister(BTPROTO_SCO);
|
||||
|
||||
proto_unregister(&sco_proto);
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
* add it to the device after the station.
|
||||
*/
|
||||
if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
|
||||
ieee80211_key_free(sdata->local, key);
|
||||
ieee80211_key_free_unused(key);
|
||||
err = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -214,8 +214,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
}
|
||||
|
||||
err = ieee80211_key_link(key, sdata, sta);
|
||||
if (err)
|
||||
ieee80211_key_free(sdata->local, key);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&sdata->local->sta_mtx);
|
||||
@ -254,7 +252,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
__ieee80211_key_free(key, true);
|
||||
ieee80211_key_free(key, true);
|
||||
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
@ -445,12 +443,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct timespec uptime;
|
||||
u64 packets = 0;
|
||||
int ac;
|
||||
|
||||
sinfo->generation = sdata->local->sta_generation;
|
||||
|
||||
sinfo->filled = STATION_INFO_INACTIVE_TIME |
|
||||
STATION_INFO_RX_BYTES |
|
||||
STATION_INFO_TX_BYTES |
|
||||
STATION_INFO_RX_BYTES64 |
|
||||
STATION_INFO_TX_BYTES64 |
|
||||
STATION_INFO_RX_PACKETS |
|
||||
STATION_INFO_TX_PACKETS |
|
||||
STATION_INFO_TX_RETRIES |
|
||||
@ -467,10 +467,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||
sinfo->connected_time = uptime.tv_sec - sta->last_connected;
|
||||
|
||||
sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
|
||||
sinfo->tx_bytes = 0;
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
sinfo->tx_bytes += sta->tx_bytes[ac];
|
||||
packets += sta->tx_packets[ac];
|
||||
}
|
||||
sinfo->tx_packets = packets;
|
||||
sinfo->rx_bytes = sta->rx_bytes;
|
||||
sinfo->tx_bytes = sta->tx_bytes;
|
||||
sinfo->rx_packets = sta->rx_packets;
|
||||
sinfo->tx_packets = sta->tx_packets;
|
||||
sinfo->tx_retries = sta->tx_retry_count;
|
||||
sinfo->tx_failed = sta->tx_retry_failed;
|
||||
sinfo->rx_dropped_misc = sta->rx_dropped;
|
||||
@ -598,8 +602,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
|
||||
data[i++] += sta->rx_fragments; \
|
||||
data[i++] += sta->rx_dropped; \
|
||||
\
|
||||
data[i++] += sta->tx_packets; \
|
||||
data[i++] += sta->tx_bytes; \
|
||||
data[i++] += sinfo.tx_packets; \
|
||||
data[i++] += sinfo.tx_bytes; \
|
||||
data[i++] += sta->tx_fragments; \
|
||||
data[i++] += sta->tx_filtered_count; \
|
||||
data[i++] += sta->tx_retry_failed; \
|
||||
@ -621,13 +625,14 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
|
||||
if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
|
||||
goto do_survey;
|
||||
|
||||
sinfo.filled = 0;
|
||||
sta_set_sinfo(sta, &sinfo);
|
||||
|
||||
i = 0;
|
||||
ADD_STA_STATS(sta);
|
||||
|
||||
data[i++] = sta->sta_state;
|
||||
|
||||
sinfo.filled = 0;
|
||||
sta_set_sinfo(sta, &sinfo);
|
||||
|
||||
if (sinfo.filled & STATION_INFO_TX_BITRATE)
|
||||
data[i] = 100000 *
|
||||
|
@ -295,7 +295,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
|
||||
char buf[50];
|
||||
struct ieee80211_key *key;
|
||||
|
||||
if (!sdata->debugfs.dir)
|
||||
if (!sdata->vif.debugfs_dir)
|
||||
return;
|
||||
|
||||
lockdep_assert_held(&sdata->local->key_mtx);
|
||||
@ -311,7 +311,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
|
||||
sprintf(buf, "../keys/%d", key->debugfs.cnt);
|
||||
sdata->debugfs.default_unicast_key =
|
||||
debugfs_create_symlink("default_unicast_key",
|
||||
sdata->debugfs.dir, buf);
|
||||
sdata->vif.debugfs_dir, buf);
|
||||
}
|
||||
|
||||
if (sdata->debugfs.default_multicast_key) {
|
||||
@ -325,7 +325,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
|
||||
sprintf(buf, "../keys/%d", key->debugfs.cnt);
|
||||
sdata->debugfs.default_multicast_key =
|
||||
debugfs_create_symlink("default_multicast_key",
|
||||
sdata->debugfs.dir, buf);
|
||||
sdata->vif.debugfs_dir, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
|
||||
char buf[50];
|
||||
struct ieee80211_key *key;
|
||||
|
||||
if (!sdata->debugfs.dir)
|
||||
if (!sdata->vif.debugfs_dir)
|
||||
return;
|
||||
|
||||
key = key_mtx_dereference(sdata->local,
|
||||
@ -343,7 +343,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
|
||||
sprintf(buf, "../keys/%d", key->debugfs.cnt);
|
||||
sdata->debugfs.default_mgmt_key =
|
||||
debugfs_create_symlink("default_mgmt_key",
|
||||
sdata->debugfs.dir, buf);
|
||||
sdata->vif.debugfs_dir, buf);
|
||||
} else
|
||||
ieee80211_debugfs_key_remove_mgmt_default(sdata);
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration,
|
||||
#endif
|
||||
|
||||
#define DEBUGFS_ADD_MODE(name, mode) \
|
||||
debugfs_create_file(#name, mode, sdata->debugfs.dir, \
|
||||
debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \
|
||||
sdata, &name##_ops);
|
||||
|
||||
#define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
|
||||
@ -577,7 +577,7 @@ static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
|
||||
static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct dentry *dir = debugfs_create_dir("mesh_stats",
|
||||
sdata->debugfs.dir);
|
||||
sdata->vif.debugfs_dir);
|
||||
#define MESHSTATS_ADD(name)\
|
||||
debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
|
||||
|
||||
@ -594,7 +594,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
||||
static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct dentry *dir = debugfs_create_dir("mesh_config",
|
||||
sdata->debugfs.dir);
|
||||
sdata->vif.debugfs_dir);
|
||||
|
||||
#define MESHPARAMS_ADD(name) \
|
||||
debugfs_create_file(#name, 0600, dir, sdata, &name##_ops);
|
||||
@ -631,7 +631,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
static void add_files(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
if (!sdata->debugfs.dir)
|
||||
if (!sdata->vif.debugfs_dir)
|
||||
return;
|
||||
|
||||
DEBUGFS_ADD(flags);
|
||||
@ -673,21 +673,21 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
char buf[10+IFNAMSIZ];
|
||||
|
||||
sprintf(buf, "netdev:%s", sdata->name);
|
||||
sdata->debugfs.dir = debugfs_create_dir(buf,
|
||||
sdata->vif.debugfs_dir = debugfs_create_dir(buf,
|
||||
sdata->local->hw.wiphy->debugfsdir);
|
||||
if (sdata->debugfs.dir)
|
||||
if (sdata->vif.debugfs_dir)
|
||||
sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
|
||||
sdata->debugfs.dir);
|
||||
sdata->vif.debugfs_dir);
|
||||
add_files(sdata);
|
||||
}
|
||||
|
||||
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
if (!sdata->debugfs.dir)
|
||||
if (!sdata->vif.debugfs_dir)
|
||||
return;
|
||||
|
||||
debugfs_remove_recursive(sdata->debugfs.dir);
|
||||
sdata->debugfs.dir = NULL;
|
||||
debugfs_remove_recursive(sdata->vif.debugfs_dir);
|
||||
sdata->vif.debugfs_dir = NULL;
|
||||
}
|
||||
|
||||
void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
@ -695,7 +695,7 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
struct dentry *dir;
|
||||
char buf[10 + IFNAMSIZ];
|
||||
|
||||
dir = sdata->debugfs.dir;
|
||||
dir = sdata->vif.debugfs_dir;
|
||||
|
||||
if (!dir)
|
||||
return;
|
||||
|
@ -241,6 +241,22 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_set_multicast_list(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct netdev_hw_addr_list *mc_list)
|
||||
{
|
||||
bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
|
||||
|
||||
trace_drv_set_multicast_list(local, sdata, mc_list->count);
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
|
||||
if (local->ops->set_multicast_list)
|
||||
local->ops->set_multicast_list(&local->hw, &sdata->vif,
|
||||
allmulti, mc_list);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline void drv_configure_filter(struct ieee80211_local *local,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
@ -531,43 +547,6 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
|
||||
local->ops->sta_remove_debugfs(&local->hw, &sdata->vif,
|
||||
sta, dir);
|
||||
}
|
||||
|
||||
static inline
|
||||
void drv_add_interface_debugfs(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
|
||||
if (!local->ops->add_interface_debugfs)
|
||||
return;
|
||||
|
||||
local->ops->add_interface_debugfs(&local->hw, &sdata->vif,
|
||||
sdata->debugfs.dir);
|
||||
}
|
||||
|
||||
static inline
|
||||
void drv_remove_interface_debugfs(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
|
||||
if (!local->ops->remove_interface_debugfs)
|
||||
return;
|
||||
|
||||
local->ops->remove_interface_debugfs(&local->hw, &sdata->vif,
|
||||
sdata->debugfs.dir);
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
void drv_add_interface_debugfs(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata) {}
|
||||
static inline
|
||||
void drv_remove_interface_debugfs(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata) {}
|
||||
#endif
|
||||
|
||||
static inline __must_check
|
||||
@ -741,13 +720,14 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local)
|
||||
local->ops->rfkill_poll(&local->hw);
|
||||
}
|
||||
|
||||
static inline void drv_flush(struct ieee80211_local *local, bool drop)
|
||||
static inline void drv_flush(struct ieee80211_local *local,
|
||||
u32 queues, bool drop)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trace_drv_flush(local, drop);
|
||||
trace_drv_flush(local, queues, drop);
|
||||
if (local->ops->flush)
|
||||
local->ops->flush(&local->hw, drop);
|
||||
local->ops->flush(&local->hw, queues, drop);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
|
@ -758,7 +758,6 @@ struct ieee80211_sub_if_data {
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct {
|
||||
struct dentry *dir;
|
||||
struct dentry *subdir_stations;
|
||||
struct dentry *default_unicast_key;
|
||||
struct dentry *default_multicast_key;
|
||||
@ -800,11 +799,6 @@ enum sdata_queue_type {
|
||||
enum {
|
||||
IEEE80211_RX_MSG = 1,
|
||||
IEEE80211_TX_STATUS_MSG = 2,
|
||||
IEEE80211_EOSP_MSG = 3,
|
||||
};
|
||||
|
||||
struct skb_eosp_msg_data {
|
||||
u8 sta[ETH_ALEN], iface[ETH_ALEN];
|
||||
};
|
||||
|
||||
enum queue_stop_reason {
|
||||
@ -815,6 +809,7 @@ enum queue_stop_reason {
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
|
||||
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
|
||||
IEEE80211_QUEUE_STOP_REASON_FLUSH,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MAC80211_LEDS
|
||||
@ -1528,8 +1523,10 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_hdr *hdr, bool ack);
|
||||
|
||||
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
|
||||
unsigned long queues,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
unsigned long queues,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason);
|
||||
@ -1546,6 +1543,8 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
{
|
||||
ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
|
||||
}
|
||||
void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg, u16 status,
|
||||
|
@ -92,7 +92,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
|
||||
return 0;
|
||||
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
|
||||
local->hw.conf.flags |= IEEE80211_CONF_IDLE;
|
||||
return IEEE80211_CONF_CHANGE_IDLE;
|
||||
@ -557,8 +557,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||
goto err_del_interface;
|
||||
}
|
||||
|
||||
drv_add_interface_debugfs(local, sdata);
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
local->fif_pspoll++;
|
||||
local->fif_probe_req++;
|
||||
@ -846,8 +844,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||
case NL80211_IFTYPE_AP:
|
||||
skb_queue_purge(&sdata->skb_queue);
|
||||
|
||||
drv_remove_interface_debugfs(local, sdata);
|
||||
|
||||
if (going_down)
|
||||
drv_remove_interface(local, sdata);
|
||||
}
|
||||
@ -919,6 +915,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
|
||||
atomic_dec(&local->iff_promiscs);
|
||||
sdata->flags ^= IEEE80211_SDATA_PROMISC;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: If somebody needs this on AP interfaces,
|
||||
* it can be enabled easily but multicast
|
||||
* addresses from VLANs need to be synced.
|
||||
*/
|
||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
|
||||
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
||||
sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
drv_set_multicast_list(local, sdata, &dev->mc);
|
||||
|
||||
spin_lock_bh(&local->filter_lock);
|
||||
__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
|
||||
spin_unlock_bh(&local->filter_lock);
|
||||
|
@ -248,11 +248,11 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
|
||||
static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
bool pairwise,
|
||||
struct ieee80211_key *old,
|
||||
struct ieee80211_key *new)
|
||||
static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
bool pairwise,
|
||||
struct ieee80211_key *old,
|
||||
struct ieee80211_key *new)
|
||||
{
|
||||
int idx;
|
||||
bool defunikey, defmultikey, defmgmtkey;
|
||||
@ -397,25 +397,21 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
||||
return key;
|
||||
}
|
||||
|
||||
static void __ieee80211_key_destroy(struct ieee80211_key *key,
|
||||
bool delay_tailroom)
|
||||
static void ieee80211_key_free_common(struct ieee80211_key *key)
|
||||
{
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Synchronize so the TX path can no longer be using
|
||||
* this key before we free/remove it.
|
||||
*/
|
||||
synchronize_net();
|
||||
|
||||
if (key->local)
|
||||
ieee80211_key_disable_hw_accel(key);
|
||||
|
||||
if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
|
||||
ieee80211_aes_key_free(key->u.ccmp.tfm);
|
||||
if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
||||
ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
|
||||
kfree(key);
|
||||
}
|
||||
|
||||
static void __ieee80211_key_destroy(struct ieee80211_key *key,
|
||||
bool delay_tailroom)
|
||||
{
|
||||
if (key->local)
|
||||
ieee80211_key_disable_hw_accel(key);
|
||||
|
||||
if (key->local) {
|
||||
struct ieee80211_sub_if_data *sdata = key->sdata;
|
||||
|
||||
@ -431,7 +427,28 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key,
|
||||
}
|
||||
}
|
||||
|
||||
kfree(key);
|
||||
ieee80211_key_free_common(key);
|
||||
}
|
||||
|
||||
static void ieee80211_key_destroy(struct ieee80211_key *key,
|
||||
bool delay_tailroom)
|
||||
{
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Synchronize so the TX path can no longer be using
|
||||
* this key before we free/remove it.
|
||||
*/
|
||||
synchronize_net();
|
||||
|
||||
__ieee80211_key_destroy(key, delay_tailroom);
|
||||
}
|
||||
|
||||
void ieee80211_key_free_unused(struct ieee80211_key *key)
|
||||
{
|
||||
WARN_ON(key->sdata || key->local);
|
||||
ieee80211_key_free_common(key);
|
||||
}
|
||||
|
||||
int ieee80211_key_link(struct ieee80211_key *key,
|
||||
@ -462,19 +479,22 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
|
||||
increment_tailroom_need_count(sdata);
|
||||
|
||||
__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
|
||||
__ieee80211_key_destroy(old_key, true);
|
||||
ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
|
||||
ieee80211_key_destroy(old_key, true);
|
||||
|
||||
ieee80211_debugfs_key_add(key);
|
||||
|
||||
ret = ieee80211_key_enable_hw_accel(key);
|
||||
|
||||
if (ret)
|
||||
ieee80211_key_free(key, true);
|
||||
|
||||
mutex_unlock(&sdata->local->key_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
|
||||
void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
|
||||
{
|
||||
if (!key)
|
||||
return;
|
||||
@ -483,18 +503,10 @@ void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
|
||||
* Replace key with nothingness if it was ever used.
|
||||
*/
|
||||
if (key->sdata)
|
||||
__ieee80211_key_replace(key->sdata, key->sta,
|
||||
ieee80211_key_replace(key->sdata, key->sta,
|
||||
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
||||
key, NULL);
|
||||
__ieee80211_key_destroy(key, delay_tailroom);
|
||||
}
|
||||
|
||||
void ieee80211_key_free(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key)
|
||||
{
|
||||
mutex_lock(&local->key_mtx);
|
||||
__ieee80211_key_free(key, true);
|
||||
mutex_unlock(&local->key_mtx);
|
||||
ieee80211_key_destroy(key, delay_tailroom);
|
||||
}
|
||||
|
||||
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
|
||||
@ -554,6 +566,7 @@ EXPORT_SYMBOL(ieee80211_iter_keys);
|
||||
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_key *key, *tmp;
|
||||
LIST_HEAD(keys);
|
||||
|
||||
cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
|
||||
|
||||
@ -565,17 +578,65 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
ieee80211_debugfs_key_remove_mgmt_default(sdata);
|
||||
|
||||
list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
|
||||
__ieee80211_key_free(key, false);
|
||||
list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
|
||||
ieee80211_key_replace(key->sdata, key->sta,
|
||||
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
||||
key, NULL);
|
||||
list_add_tail(&key->list, &keys);
|
||||
}
|
||||
|
||||
ieee80211_debugfs_key_update_default(sdata);
|
||||
|
||||
if (!list_empty(&keys)) {
|
||||
synchronize_net();
|
||||
list_for_each_entry_safe(key, tmp, &keys, list)
|
||||
__ieee80211_key_destroy(key, false);
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
|
||||
sdata->crypto_tx_tailroom_pending_dec);
|
||||
|
||||
mutex_unlock(&sdata->local->key_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_key *key, *tmp;
|
||||
LIST_HEAD(keys);
|
||||
int i;
|
||||
|
||||
mutex_lock(&local->key_mtx);
|
||||
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
|
||||
key = key_mtx_dereference(local, sta->gtk[i]);
|
||||
if (!key)
|
||||
continue;
|
||||
ieee80211_key_replace(key->sdata, key->sta,
|
||||
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
||||
key, NULL);
|
||||
list_add(&key->list, &keys);
|
||||
}
|
||||
|
||||
key = key_mtx_dereference(local, sta->ptk);
|
||||
if (key) {
|
||||
ieee80211_key_replace(key->sdata, key->sta,
|
||||
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
||||
key, NULL);
|
||||
list_add(&key->list, &keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: the station code relies on this being
|
||||
* done even if there aren't any keys
|
||||
*/
|
||||
synchronize_net();
|
||||
|
||||
list_for_each_entry_safe(key, tmp, &keys, list)
|
||||
__ieee80211_key_destroy(key, true);
|
||||
|
||||
mutex_unlock(&local->key_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_delayed_tailroom_dec(struct work_struct *wk)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
@ -129,19 +129,20 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
||||
size_t seq_len, const u8 *seq);
|
||||
/*
|
||||
* Insert a key into data structures (sdata, sta if necessary)
|
||||
* to make it used, free old key.
|
||||
* to make it used, free old key. On failure, also free the new key.
|
||||
*/
|
||||
int __must_check ieee80211_key_link(struct ieee80211_key *key,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta);
|
||||
void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
|
||||
void ieee80211_key_free(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key);
|
||||
int ieee80211_key_link(struct ieee80211_key *key,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta);
|
||||
void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
|
||||
void ieee80211_key_free_unused(struct ieee80211_key *key);
|
||||
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
|
||||
bool uni, bool multi);
|
||||
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
|
||||
int idx);
|
||||
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
||||
struct sta_info *sta);
|
||||
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
#define key_mtx_dereference(local, ref) \
|
||||
|
@ -100,7 +100,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
int power;
|
||||
enum nl80211_channel_type channel_type;
|
||||
u32 offchannel_flag;
|
||||
bool scanning = false;
|
||||
|
||||
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
|
||||
if (local->scan_channel) {
|
||||
@ -147,9 +146,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
changed |= IEEE80211_CONF_CHANGE_SMPS;
|
||||
}
|
||||
|
||||
scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
|
||||
test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
|
||||
test_bit(SCAN_HW_SCANNING, &local->scanning);
|
||||
power = chan->max_power;
|
||||
|
||||
rcu_read_lock();
|
||||
@ -226,8 +222,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
|
||||
static void ieee80211_tasklet_handler(unsigned long data)
|
||||
{
|
||||
struct ieee80211_local *local = (struct ieee80211_local *) data;
|
||||
struct sta_info *sta, *tmp;
|
||||
struct skb_eosp_msg_data *eosp_data;
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&local->skb_queue)) ||
|
||||
@ -243,18 +237,6 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
||||
skb->pkt_type = 0;
|
||||
ieee80211_tx_status(&local->hw, skb);
|
||||
break;
|
||||
case IEEE80211_EOSP_MSG:
|
||||
eosp_data = (void *)skb->cb;
|
||||
for_each_sta_info(local, eosp_data->sta, sta, tmp) {
|
||||
/* skip wrong virtual interface */
|
||||
if (memcmp(eosp_data->iface,
|
||||
sta->sdata->vif.addr, ETH_ALEN))
|
||||
continue;
|
||||
clear_sta_flag(sta, WLAN_STA_SP);
|
||||
break;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "mac80211: Packet is of unknown type %d\n",
|
||||
skb->pkt_type);
|
||||
@ -295,8 +277,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
|
||||
"Hardware restart was requested\n");
|
||||
|
||||
/* use this reason, ieee80211_reconfig will unblock it */
|
||||
ieee80211_stop_queues_by_reason(hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
|
||||
/*
|
||||
* Stop all Rx during the reconfig. We don't want state changes
|
||||
|
@ -699,10 +699,8 @@ out_free:
|
||||
static int
|
||||
ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct beacon_data *old_bcn;
|
||||
int ret;
|
||||
sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
|
||||
|
||||
mutex_lock(&ifmsh->mtx);
|
||||
|
||||
@ -833,9 +831,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_mgmt *hdr;
|
||||
struct ieee802_11_elems elems;
|
||||
size_t baselen;
|
||||
u8 *pos, *end;
|
||||
u8 *pos;
|
||||
|
||||
end = ((u8 *) mgmt) + len;
|
||||
pos = mgmt->u.probe_req.variable;
|
||||
baselen = (u8 *) pos - (u8 *) mgmt;
|
||||
if (baselen > len)
|
||||
|
@ -1009,6 +1009,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||
|
||||
/* XXX: wait for a beacon first? */
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
out:
|
||||
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
|
||||
@ -1108,6 +1109,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
if (sw_elem->mode)
|
||||
ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
if (sdata->local->ops->channel_switch) {
|
||||
@ -1375,6 +1377,7 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_PS);
|
||||
}
|
||||
|
||||
@ -1436,7 +1439,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
|
||||
else {
|
||||
ieee80211_send_nullfunc(local, sdata, 1);
|
||||
/* Flush to get the tx status of nullfunc frame */
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1767,7 +1770,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
|
||||
if (tx)
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
|
||||
/* deauthenticate/disassociate now */
|
||||
if (tx || frame_buf)
|
||||
@ -1776,7 +1779,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/* flush out frame */
|
||||
if (tx)
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
|
||||
/* clear bssid only after building the needed mgmt frames */
|
||||
memset(ifmgd->bssid, 0, ETH_ALEN);
|
||||
@ -1948,7 +1951,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
|
||||
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
|
||||
run_again(ifmgd, ifmgd->probe_timeout);
|
||||
if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
||||
drv_flush(sdata->local, false);
|
||||
ieee80211_flush_queues(sdata->local, sdata);
|
||||
}
|
||||
|
||||
static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
|
||||
@ -2071,6 +2074,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
|
||||
true, frame_buf);
|
||||
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
|
@ -118,9 +118,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
|
||||
* Stop queues and transmit all frames queued by the driver
|
||||
* before sending nullfunc to enable powersave at the AP.
|
||||
*/
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
@ -181,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
|
||||
}
|
||||
|
||||
@ -373,7 +373,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
|
||||
ieee80211_roc_notify_destroy(roc);
|
||||
|
||||
if (started) {
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
|
||||
local->tmp_channel = NULL;
|
||||
ieee80211_hw_config(local, 0);
|
||||
|
@ -30,12 +30,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
}
|
||||
|
||||
ieee80211_stop_queues_by_reason(hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
|
||||
/* flush out all packets */
|
||||
synchronize_net();
|
||||
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
|
||||
local->quiescing = true;
|
||||
/* make quiescing visible to timers everywhere */
|
||||
@ -68,6 +69,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
}
|
||||
ieee80211_wake_queues_by_reason(hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
return err;
|
||||
} else if (err > 0) {
|
||||
|
@ -202,14 +202,23 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
|
||||
struct minstrel_rate_stats *mr;
|
||||
unsigned int nsecs = 0;
|
||||
unsigned int tp;
|
||||
unsigned int prob;
|
||||
|
||||
mr = &mi->groups[group].rates[rate];
|
||||
prob = mr->probability;
|
||||
|
||||
if (mr->probability < MINSTREL_FRAC(1, 10)) {
|
||||
if (prob < MINSTREL_FRAC(1, 10)) {
|
||||
mr->cur_tp = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the throughput calculation, limit the probability value to 90% to
|
||||
* account for collision related packet error rate fluctuation
|
||||
*/
|
||||
if (prob > MINSTREL_FRAC(9, 10))
|
||||
prob = MINSTREL_FRAC(9, 10);
|
||||
|
||||
if (group != MINSTREL_CCK_GROUP)
|
||||
nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
|
||||
|
||||
@ -639,15 +648,18 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
|
||||
/*
|
||||
* Sampling might add some overhead (RTS, no aggregation)
|
||||
* to the frame. Hence, don't use sampling for the currently
|
||||
* used max TP rate.
|
||||
* used rates.
|
||||
*/
|
||||
if (sample_idx == mi->max_tp_rate)
|
||||
if (sample_idx == mi->max_tp_rate ||
|
||||
sample_idx == mi->max_tp_rate2 ||
|
||||
sample_idx == mi->max_prob_rate)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* When not using MRR, do not sample if the probability is already
|
||||
* higher than 95% to avoid wasting airtime
|
||||
* Do not sample if the probability is already higher than 95%
|
||||
* to avoid wasting airtime.
|
||||
*/
|
||||
if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
|
||||
if (mr->probability > MINSTREL_FRAC(95, 100))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
|
@ -153,7 +153,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
|
||||
u8 *elements;
|
||||
struct ieee80211_channel *channel;
|
||||
size_t baselen;
|
||||
bool beacon;
|
||||
struct ieee802_11_elems elems;
|
||||
|
||||
if (skb->len < 24 ||
|
||||
@ -175,11 +174,9 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
|
||||
|
||||
elements = mgmt->u.probe_resp.variable;
|
||||
baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
||||
beacon = false;
|
||||
} else {
|
||||
baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||
elements = mgmt->u.beacon.variable;
|
||||
beacon = true;
|
||||
}
|
||||
|
||||
if (baselen > skb->len)
|
||||
@ -335,7 +332,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
ieee80211_offchannel_stop_vifs(local);
|
||||
|
||||
/* ensure nullfunc is transmitted before leaving operating channel */
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
@ -671,7 +668,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local,
|
||||
ieee80211_offchannel_stop_vifs(local);
|
||||
|
||||
if (local->ops->flush) {
|
||||
drv_flush(local, false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
*next_delay = 0;
|
||||
} else
|
||||
*next_delay = HZ / 10;
|
||||
|
@ -556,6 +556,15 @@ static inline void __bss_tim_clear(u8 *tim, u16 id)
|
||||
tim[id / 8] &= ~(1 << (id % 8));
|
||||
}
|
||||
|
||||
static inline bool __bss_tim_get(u8 *tim, u16 id)
|
||||
{
|
||||
/*
|
||||
* This format has been mandated by the IEEE specifications,
|
||||
* so this line may not be changed to use the test_bit() format.
|
||||
*/
|
||||
return tim[id / 8] & (1 << (id % 8));
|
||||
}
|
||||
|
||||
static unsigned long ieee80211_tids_for_ac(int ac)
|
||||
{
|
||||
/* If we ever support TIDs > 7, this obviously needs to be adjusted */
|
||||
@ -636,6 +645,9 @@ void sta_info_recalc_tim(struct sta_info *sta)
|
||||
done:
|
||||
spin_lock_bh(&local->tim_lock);
|
||||
|
||||
if (indicate_tim == __bss_tim_get(ps->tim, id))
|
||||
goto out_unlock;
|
||||
|
||||
if (indicate_tim)
|
||||
__bss_tim_set(ps->tim, id);
|
||||
else
|
||||
@ -647,6 +659,7 @@ void sta_info_recalc_tim(struct sta_info *sta)
|
||||
local->tim_in_locked_section = false;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_bh(&local->tim_lock);
|
||||
}
|
||||
|
||||
@ -770,7 +783,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
@ -797,14 +810,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||
|
||||
list_del_rcu(&sta->list);
|
||||
|
||||
mutex_lock(&local->key_mtx);
|
||||
for (i = 0; i < NUM_DEFAULT_KEYS; i++)
|
||||
__ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]),
|
||||
true);
|
||||
if (sta->ptk)
|
||||
__ieee80211_key_free(key_mtx_dereference(local, sta->ptk),
|
||||
true);
|
||||
mutex_unlock(&local->key_mtx);
|
||||
/* this always calls synchronize_net() */
|
||||
ieee80211_free_sta_keys(local, sta);
|
||||
|
||||
sta->dead = true;
|
||||
|
||||
@ -1390,30 +1397,16 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_sta_block_awake);
|
||||
|
||||
void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta)
|
||||
void ieee80211_sta_eosp(struct ieee80211_sta *pubsta)
|
||||
{
|
||||
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct sk_buff *skb;
|
||||
struct skb_eosp_msg_data *data;
|
||||
|
||||
trace_api_eosp(local, pubsta);
|
||||
|
||||
skb = alloc_skb(0, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
/* too bad ... but race is better than loss */
|
||||
clear_sta_flag(sta, WLAN_STA_SP);
|
||||
return;
|
||||
}
|
||||
|
||||
data = (void *)skb->cb;
|
||||
memcpy(data->sta, pubsta->addr, ETH_ALEN);
|
||||
memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN);
|
||||
skb->pkt_type = IEEE80211_EOSP_MSG;
|
||||
skb_queue_tail(&local->skb_queue, skb);
|
||||
tasklet_schedule(&local->tasklet);
|
||||
clear_sta_flag(sta, WLAN_STA_SP);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe);
|
||||
EXPORT_SYMBOL(ieee80211_sta_eosp);
|
||||
|
||||
void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
|
||||
u8 tid, bool buffered)
|
||||
|
@ -333,7 +333,8 @@ struct sta_info {
|
||||
unsigned long driver_buffered_tids;
|
||||
|
||||
/* Updated from RX path only, no locking requirements */
|
||||
unsigned long rx_packets, rx_bytes;
|
||||
unsigned long rx_packets;
|
||||
u64 rx_bytes;
|
||||
unsigned long wep_weak_iv_count;
|
||||
unsigned long last_rx;
|
||||
long last_connected;
|
||||
@ -353,9 +354,9 @@ struct sta_info {
|
||||
unsigned int fail_avg;
|
||||
|
||||
/* Updated from TX path only, no locking requirements */
|
||||
unsigned long tx_packets;
|
||||
unsigned long tx_bytes;
|
||||
unsigned long tx_fragments;
|
||||
u32 tx_fragments;
|
||||
u64 tx_packets[IEEE80211_NUM_ACS];
|
||||
u64 tx_bytes[IEEE80211_NUM_ACS];
|
||||
struct ieee80211_tx_rate last_tx_rate;
|
||||
int last_rx_rate_idx;
|
||||
u32 last_rx_rate_flag;
|
||||
|
@ -431,6 +431,30 @@ TRACE_EVENT(drv_prepare_multicast,
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_set_multicast_list,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata, int mc_count),
|
||||
|
||||
TP_ARGS(local, sdata, mc_count),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(bool, allmulti)
|
||||
__field(int, mc_count)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
|
||||
__entry->mc_count = mc_count;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d",
|
||||
LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_configure_filter,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
unsigned int changed_flags,
|
||||
@ -940,23 +964,26 @@ TRACE_EVENT(drv_get_survey,
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_flush,
|
||||
TP_PROTO(struct ieee80211_local *local, bool drop),
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
u32 queues, bool drop),
|
||||
|
||||
TP_ARGS(local, drop),
|
||||
TP_ARGS(local, queues, drop),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(bool, drop)
|
||||
__field(u32, queues)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->drop = drop;
|
||||
__entry->queues = queues;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " drop:%d",
|
||||
LOCAL_PR_ARG, __entry->drop
|
||||
LOCAL_PR_FMT " queues:0x%x drop:%d",
|
||||
LOCAL_PR_ARG, __entry->queues, __entry->drop
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -233,6 +233,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
|
||||
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_PS);
|
||||
ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
|
||||
ieee80211_queue_work(&local->hw,
|
||||
@ -991,15 +992,18 @@ static ieee80211_tx_result debug_noinline
|
||||
ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ac = -1;
|
||||
|
||||
if (!tx->sta)
|
||||
return TX_CONTINUE;
|
||||
|
||||
tx->sta->tx_packets++;
|
||||
skb_queue_walk(&tx->skbs, skb) {
|
||||
ac = skb_get_queue_mapping(skb);
|
||||
tx->sta->tx_fragments++;
|
||||
tx->sta->tx_bytes += skb->len;
|
||||
tx->sta->tx_bytes[ac] += skb->len;
|
||||
}
|
||||
if (ac >= 0)
|
||||
tx->sta->tx_packets[ac]++;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
@ -453,7 +453,8 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
}
|
||||
|
||||
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
enum queue_stop_reason reason)
|
||||
unsigned long queues,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
unsigned long flags;
|
||||
@ -461,7 +462,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
for (i = 0; i < hw->queues; i++)
|
||||
for_each_set_bit(i, &queues, hw->queues)
|
||||
__ieee80211_stop_queue(hw, i, reason);
|
||||
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
@ -469,7 +470,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
|
||||
void ieee80211_stop_queues(struct ieee80211_hw *hw)
|
||||
{
|
||||
ieee80211_stop_queues_by_reason(hw,
|
||||
ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_DRIVER);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_stop_queues);
|
||||
@ -491,6 +492,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
|
||||
EXPORT_SYMBOL(ieee80211_queue_stopped);
|
||||
|
||||
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
|
||||
unsigned long queues,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
@ -499,7 +501,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
for (i = 0; i < hw->queues; i++)
|
||||
for_each_set_bit(i, &queues, hw->queues)
|
||||
__ieee80211_wake_queue(hw, i, reason);
|
||||
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
@ -507,10 +509,42 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
|
||||
|
||||
void ieee80211_wake_queues(struct ieee80211_hw *hw)
|
||||
{
|
||||
ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER);
|
||||
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_DRIVER);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_wake_queues);
|
||||
|
||||
void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
u32 queues;
|
||||
|
||||
if (!local->ops->flush)
|
||||
return;
|
||||
|
||||
if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
|
||||
int ac;
|
||||
|
||||
queues = 0;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
queues |= BIT(sdata->vif.hw_queue[ac]);
|
||||
if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
|
||||
queues |= BIT(sdata->vif.cab_queue);
|
||||
} else {
|
||||
/* all queues */
|
||||
queues = BIT(local->hw.queues) - 1;
|
||||
}
|
||||
|
||||
ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_FLUSH);
|
||||
|
||||
drv_flush(local, queues, false);
|
||||
|
||||
ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_FLUSH);
|
||||
}
|
||||
|
||||
void ieee80211_iterate_active_interfaces(
|
||||
struct ieee80211_hw *hw, u32 iter_flags,
|
||||
void (*iterator)(void *data, u8 *mac,
|
||||
@ -1651,8 +1685,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
}
|
||||
|
||||
ieee80211_wake_queues_by_reason(hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
|
||||
/*
|
||||
* If this is for hw restart things are still running.
|
||||
|
@ -1096,8 +1096,10 @@ static int __init cfg80211_init(void)
|
||||
goto out_fail_reg;
|
||||
|
||||
cfg80211_wq = create_singlethread_workqueue("cfg80211");
|
||||
if (!cfg80211_wq)
|
||||
if (!cfg80211_wq) {
|
||||
err = -ENOMEM;
|
||||
goto out_fail_wq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -234,7 +234,7 @@ void cfg80211_conn_work(struct work_struct *work)
|
||||
wdev_unlock(wdev);
|
||||
continue;
|
||||
}
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTING) {
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTING || !wdev->conn) {
|
||||
wdev_unlock(wdev);
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user