mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts: drivers/net/wireless/iwlwifi/dvm/tx.c drivers/net/wireless/ti/wlcore/sdio.c drivers/net/wireless/ti/wlcore/spi.c
This commit is contained in:
commit
98d5fac233
@ -309,7 +309,7 @@ static struct omap2_hsmmc_info mmc[] = {
|
||||
.gpio_wp = 63,
|
||||
.deferred = true,
|
||||
},
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
{
|
||||
.name = "wl1271",
|
||||
.mmc = 2,
|
||||
@ -450,7 +450,7 @@ static struct regulator_init_data omap3evm_vio = {
|
||||
.consumer_supplies = omap3evm_vio_supply,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
|
||||
#define OMAP3EVM_WLAN_PMENA_GPIO (150)
|
||||
#define OMAP3EVM_WLAN_IRQ_GPIO (149)
|
||||
@ -563,7 +563,7 @@ static struct omap_board_mux omap35x_board_mux[] __initdata = {
|
||||
OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
|
||||
OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
@ -601,7 +601,7 @@ static struct omap_board_mux omap36x_board_mux[] __initdata = {
|
||||
OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
@ -637,7 +637,7 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {
|
||||
|
||||
static void __init omap3_evm_wl12xx_init(void)
|
||||
{
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
int ret;
|
||||
|
||||
/* WL12xx WLAN Init */
|
||||
|
@ -1613,6 +1613,10 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
ah->ah_cal_mask |= AR5K_CALIBRATION_NF;
|
||||
|
||||
ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel);
|
||||
if (WARN_ON(ee_mode < 0)) {
|
||||
ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF;
|
||||
return;
|
||||
}
|
||||
|
||||
/* completed NF calibration, test threshold */
|
||||
nf = ath5k_hw_read_measured_noise_floor(ah);
|
||||
|
@ -985,6 +985,8 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
||||
return;
|
||||
|
||||
ee_mode = ath5k_eeprom_mode_from_channel(channel);
|
||||
if (WARN_ON(ee_mode < 0))
|
||||
return;
|
||||
|
||||
/* Adjust power delta for channel 14 */
|
||||
if (channel->center_freq == 2484)
|
||||
|
@ -427,6 +427,30 @@ static bool ath6kl_is_tx_pending(struct ath6kl *ar)
|
||||
return ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0;
|
||||
}
|
||||
|
||||
static void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
|
||||
return;
|
||||
|
||||
if (vif->nw_type != INFRA_NETWORK)
|
||||
return;
|
||||
|
||||
if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
|
||||
vif->ar->fw_capabilities))
|
||||
return;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
|
||||
enable ? "enable" : "disable");
|
||||
|
||||
err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, enable);
|
||||
if (err)
|
||||
ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
|
||||
enable ? "enable" : "disable", err);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_connect_params *sme)
|
||||
@ -616,13 +640,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
||||
vif->req_bssid, vif->ch_hint,
|
||||
ar->connect_ctrl_flags, nw_subtype);
|
||||
|
||||
/* disable background scan if period is 0 */
|
||||
if (sme->bg_scan_period == 0)
|
||||
if (sme->bg_scan_period == 0) {
|
||||
/* disable background scan if period is 0 */
|
||||
sme->bg_scan_period = 0xffff;
|
||||
|
||||
/* configure default value if not specified */
|
||||
if (sme->bg_scan_period == -1)
|
||||
} else if (sme->bg_scan_period == -1) {
|
||||
/* configure default value if not specified */
|
||||
sme->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
|
||||
}
|
||||
|
||||
ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0, 0,
|
||||
sme->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
|
||||
@ -767,7 +791,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
|
||||
nw_type & ADHOC_CREATOR ? "creator" : "joiner");
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(ar->wiphy, bss);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -778,7 +802,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
||||
assoc_req_ie, assoc_req_len,
|
||||
assoc_resp_ie, assoc_resp_len,
|
||||
WLAN_STATUS_SUCCESS, GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(ar->wiphy, bss);
|
||||
} else if (vif->sme_state == SME_CONNECTED) {
|
||||
/* inform roam event to cfg80211 */
|
||||
cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len,
|
||||
@ -1454,10 +1478,10 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
|
||||
return -EIO;
|
||||
|
||||
if (pmgmt) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
|
||||
mode.pwr_mode = REC_POWER;
|
||||
} else {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
|
||||
mode.pwr_mode = MAX_PERF_POWER;
|
||||
}
|
||||
|
||||
@ -1509,7 +1533,7 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
|
||||
list_del(&vif->list);
|
||||
spin_unlock_bh(&ar->list_lock);
|
||||
|
||||
ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
|
||||
ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag));
|
||||
|
||||
ath6kl_cfg80211_vif_cleanup(vif);
|
||||
|
||||
@ -1559,17 +1583,13 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
|
||||
set_iface_type:
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
vif->next_mode = INFRA_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
vif->next_mode = ADHOC_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
vif->next_mode = AP_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
vif->next_mode = INFRA_NETWORK;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
vif->next_mode = AP_NETWORK;
|
||||
break;
|
||||
@ -1778,14 +1798,14 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
if (vif->target_stats.rx_byte) {
|
||||
sinfo->rx_bytes = vif->target_stats.rx_byte;
|
||||
sinfo->filled |= STATION_INFO_RX_BYTES;
|
||||
sinfo->filled |= STATION_INFO_RX_BYTES64;
|
||||
sinfo->rx_packets = vif->target_stats.rx_pkt;
|
||||
sinfo->filled |= STATION_INFO_RX_PACKETS;
|
||||
}
|
||||
|
||||
if (vif->target_stats.tx_byte) {
|
||||
sinfo->tx_bytes = vif->target_stats.tx_byte;
|
||||
sinfo->filled |= STATION_INFO_TX_BYTES;
|
||||
sinfo->filled |= STATION_INFO_TX_BYTES64;
|
||||
sinfo->tx_packets = vif->target_stats.tx_pkt;
|
||||
sinfo->filled |= STATION_INFO_TX_PACKETS;
|
||||
}
|
||||
@ -2673,30 +2693,6 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
|
||||
return;
|
||||
|
||||
if (vif->nw_type != INFRA_NETWORK)
|
||||
return;
|
||||
|
||||
if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
|
||||
vif->ar->fw_capabilities))
|
||||
return;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
|
||||
enable ? "enable" : "disable");
|
||||
|
||||
err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, enable);
|
||||
if (err)
|
||||
ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
|
||||
enable ? "enable" : "disable", err);
|
||||
}
|
||||
|
||||
static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
|
||||
u8 *rsn_capab)
|
||||
{
|
||||
@ -2776,9 +2772,11 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
ar->ap_mode_bkey.valid = false;
|
||||
|
||||
/* TODO:
|
||||
* info->interval
|
||||
*/
|
||||
ret = ath6kl_wmi_ap_set_beacon_intvl_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
info->beacon_interval);
|
||||
|
||||
if (ret)
|
||||
ath6kl_warn("Failed to set beacon interval: %d\n", ret);
|
||||
|
||||
ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
info->dtim_period);
|
||||
@ -3557,6 +3555,37 @@ static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready)
|
||||
{
|
||||
static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
bool discon_issued;
|
||||
|
||||
netif_stop_queue(vif->ndev);
|
||||
|
||||
clear_bit(WLAN_ENABLED, &vif->flags);
|
||||
|
||||
if (wmi_ready) {
|
||||
discon_issued = test_bit(CONNECTED, &vif->flags) ||
|
||||
test_bit(CONNECT_PEND, &vif->flags);
|
||||
ath6kl_disconnect(vif);
|
||||
del_timer(&vif->disconnect_timer);
|
||||
|
||||
if (discon_issued)
|
||||
ath6kl_disconnect_event(vif, DISCONNECT_CMD,
|
||||
(vif->nw_type & AP_NETWORK) ?
|
||||
bcast_mac : vif->bssid,
|
||||
0, NULL, 0);
|
||||
}
|
||||
|
||||
if (vif->scan_req) {
|
||||
cfg80211_scan_done(vif->scan_req, true);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
/* need to clean up enhanced bmiss detection fw state */
|
||||
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
|
||||
}
|
||||
|
||||
void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
|
||||
{
|
||||
struct ath6kl *ar = vif->ar;
|
||||
|
@ -61,7 +61,5 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);
|
||||
|
||||
struct ath6kl *ath6kl_cfg80211_create(void);
|
||||
void ath6kl_cfg80211_destroy(struct ath6kl *ar);
|
||||
/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
|
||||
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);
|
||||
|
||||
#endif /* ATH6KL_CFG80211_H */
|
||||
|
@ -940,7 +940,7 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
|
||||
bool wait_fot_compltn, bool cold_reset);
|
||||
void ath6kl_init_control_info(struct ath6kl_vif *vif);
|
||||
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
|
||||
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
|
||||
void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready);
|
||||
int ath6kl_init_hw_start(struct ath6kl *ar);
|
||||
int ath6kl_init_hw_stop(struct ath6kl *ar);
|
||||
int ath6kl_init_fetch_firmwares(struct ath6kl *ar);
|
||||
|
@ -509,9 +509,7 @@ static void destroy_htc_txctrl_packet(struct htc_packet *packet)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
skb = packet->skb;
|
||||
if (skb != NULL)
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
kfree(packet);
|
||||
}
|
||||
|
||||
@ -969,6 +967,22 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
|
||||
u16 payload_len;
|
||||
int status = 0;
|
||||
|
||||
/*
|
||||
* ar->htc_target can be NULL due to a race condition that can occur
|
||||
* during driver initialization(we do 'ath6kl_hif_power_on' before
|
||||
* initializing 'ar->htc_target' via 'ath6kl_htc_create').
|
||||
* 'ath6kl_hif_power_on' assigns 'ath6kl_recv_complete' as
|
||||
* usb_complete_t/callback function for 'usb_fill_bulk_urb'.
|
||||
* Thus the possibility of ar->htc_target being NULL
|
||||
* via ath6kl_recv_complete -> ath6kl_usb_io_comp_work.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!target)) {
|
||||
ath6kl_err("Target not yet initialized\n");
|
||||
status = -EINVAL;
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
|
||||
netdata = skb->data;
|
||||
netlen = skb->len;
|
||||
|
||||
@ -1054,6 +1068,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
@ -1089,8 +1104,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
|
||||
skb = NULL;
|
||||
|
||||
free_skb:
|
||||
if (skb != NULL)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return status;
|
||||
|
||||
@ -1184,7 +1198,7 @@ static void reset_endpoint_states(struct htc_target *target)
|
||||
INIT_LIST_HEAD(&ep->pipe.tx_lookup_queue);
|
||||
INIT_LIST_HEAD(&ep->rx_bufq);
|
||||
ep->target = target;
|
||||
ep->pipe.tx_credit_flow_enabled = (bool) 1; /* FIXME */
|
||||
ep->pipe.tx_credit_flow_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1715,38 +1715,6 @@ void ath6kl_init_hw_restart(struct ath6kl *ar)
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
|
||||
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
|
||||
{
|
||||
static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
bool discon_issued;
|
||||
|
||||
netif_stop_queue(vif->ndev);
|
||||
|
||||
clear_bit(WLAN_ENABLED, &vif->flags);
|
||||
|
||||
if (wmi_ready) {
|
||||
discon_issued = test_bit(CONNECTED, &vif->flags) ||
|
||||
test_bit(CONNECT_PEND, &vif->flags);
|
||||
ath6kl_disconnect(vif);
|
||||
del_timer(&vif->disconnect_timer);
|
||||
|
||||
if (discon_issued)
|
||||
ath6kl_disconnect_event(vif, DISCONNECT_CMD,
|
||||
(vif->nw_type & AP_NETWORK) ?
|
||||
bcast_mac : vif->bssid,
|
||||
0, NULL, 0);
|
||||
}
|
||||
|
||||
if (vif->scan_req) {
|
||||
cfg80211_scan_done(vif->scan_req, true);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
/* need to clean up enhanced bmiss detection fw state */
|
||||
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
|
||||
}
|
||||
|
||||
void ath6kl_stop_txrx(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_vif *vif, *tmp_vif;
|
||||
@ -1766,7 +1734,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
|
||||
list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
|
||||
list_del(&vif->list);
|
||||
spin_unlock_bh(&ar->list_lock);
|
||||
ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
|
||||
ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag));
|
||||
rtnl_lock();
|
||||
ath6kl_cfg80211_vif_cleanup(vif);
|
||||
rtnl_unlock();
|
||||
@ -1801,8 +1769,6 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
|
||||
"attempting to reset target on instance destroy\n");
|
||||
ath6kl_reset_device(ar, ar->target_type, true, true);
|
||||
|
||||
clear_bit(WLAN_ENABLED, &ar->flag);
|
||||
|
||||
up(&ar->sem);
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_stop_txrx);
|
||||
|
@ -159,10 +159,8 @@ static void ath6kl_usb_free_urb_to_pipe(struct ath6kl_usb_pipe *pipe,
|
||||
|
||||
static void ath6kl_usb_cleanup_recv_urb(struct ath6kl_urb_context *urb_context)
|
||||
{
|
||||
if (urb_context->skb != NULL) {
|
||||
dev_kfree_skb(urb_context->skb);
|
||||
urb_context->skb = NULL;
|
||||
}
|
||||
dev_kfree_skb(urb_context->skb);
|
||||
urb_context->skb = NULL;
|
||||
|
||||
ath6kl_usb_free_urb_to_pipe(urb_context->pipe, urb_context);
|
||||
}
|
||||
|
@ -751,6 +751,23 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
|
||||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_ap_set_beacon_intvl_cmd(struct wmi *wmi, u8 if_idx,
|
||||
u32 beacon_intvl)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct set_beacon_int_cmd *cmd;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct set_beacon_int_cmd *) skb->data;
|
||||
|
||||
cmd->beacon_intvl = cpu_to_le32(beacon_intvl);
|
||||
return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
|
||||
WMI_SET_BEACON_INT_CMDID, NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
@ -1108,7 +1125,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
|
||||
kfree(mgmt);
|
||||
if (bss == NULL)
|
||||
return -ENOMEM;
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(ar->wiphy, bss);
|
||||
|
||||
/*
|
||||
* Firmware doesn't return any event when scheduled scan has
|
||||
@ -2480,16 +2497,11 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
|
||||
|
||||
free_cmd_skb:
|
||||
/* free up any resources left over (possibly due to an error) */
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
free_data_skb:
|
||||
for (index = 0; index < num_pri_streams; index++) {
|
||||
if (data_sync_bufs[index].skb != NULL) {
|
||||
dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
|
||||
skb);
|
||||
}
|
||||
}
|
||||
for (index = 0; index < num_pri_streams; index++)
|
||||
dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1660,6 +1660,10 @@ struct roam_ctrl_cmd {
|
||||
u8 roam_ctrl;
|
||||
} __packed;
|
||||
|
||||
struct set_beacon_int_cmd {
|
||||
__le32 beacon_intvl;
|
||||
} __packed;
|
||||
|
||||
struct set_dtim_cmd {
|
||||
__le32 dtim_period;
|
||||
} __packed;
|
||||
@ -2649,6 +2653,8 @@ int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
|
||||
int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi);
|
||||
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
|
||||
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
|
||||
int ath6kl_wmi_ap_set_beacon_intvl_cmd(struct wmi *wmi, u8 if_idx,
|
||||
u32 beacon_interval);
|
||||
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
|
||||
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
|
||||
int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
|
||||
|
@ -389,6 +389,7 @@ struct ath_beacon_config {
|
||||
u16 bmiss_timeout;
|
||||
u8 dtim_count;
|
||||
bool enable_beacon;
|
||||
bool ibss_creator;
|
||||
};
|
||||
|
||||
struct ath_beacon {
|
||||
|
@ -407,12 +407,17 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval)
|
||||
/*
|
||||
* Both nexttbtt and intval have to be in usecs.
|
||||
*/
|
||||
static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
|
||||
u32 intval, bool reset_tsf)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath9k_hw_reset_tsf(ah);
|
||||
if (reset_tsf)
|
||||
ath9k_hw_reset_tsf(ah);
|
||||
ath9k_beaconq_config(sc);
|
||||
ath9k_hw_beaconinit(ah, nexttbtt, intval);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
@ -442,10 +447,12 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
|
||||
else
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
ath_dbg(common, BEACON,
|
||||
"AP (%s) nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
(conf->enable_beacon) ? "Enable" : "Disable",
|
||||
nexttbtt, intval, conf->beacon_interval);
|
||||
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -586,17 +593,45 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
|
||||
ath9k_reset_beacon_status(sc);
|
||||
|
||||
intval = TU_TO_USEC(conf->beacon_interval);
|
||||
nexttbtt = intval;
|
||||
|
||||
if (conf->ibss_creator) {
|
||||
nexttbtt = intval;
|
||||
} else {
|
||||
u32 tbtt, offset, tsftu;
|
||||
u64 tsf;
|
||||
|
||||
/*
|
||||
* Pull nexttbtt forward to reflect the current
|
||||
* sync'd TSF.
|
||||
*/
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
|
||||
offset = tsftu % conf->beacon_interval;
|
||||
tbtt = tsftu - offset;
|
||||
if (offset)
|
||||
tbtt += conf->beacon_interval;
|
||||
|
||||
nexttbtt = TU_TO_USEC(tbtt);
|
||||
}
|
||||
|
||||
if (conf->enable_beacon)
|
||||
ah->imask |= ATH9K_INT_SWBA;
|
||||
else
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
ath_dbg(common, BEACON,
|
||||
"IBSS (%s) nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
(conf->enable_beacon) ? "Enable" : "Disable",
|
||||
nexttbtt, intval, conf->beacon_interval);
|
||||
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval, conf->ibss_creator);
|
||||
|
||||
/*
|
||||
* Set the global 'beacon has been configured' flag for the
|
||||
* joiner case in IBSS mode.
|
||||
*/
|
||||
if (!conf->ibss_creator && conf->enable_beacon)
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
|
||||
bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
@ -639,6 +674,7 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
|
||||
cur_conf->dtim_period = bss_conf->dtim_period;
|
||||
cur_conf->listen_interval = 1;
|
||||
cur_conf->dtim_count = 1;
|
||||
cur_conf->ibss_creator = bss_conf->ibss_creator;
|
||||
cur_conf->bmiss_timeout =
|
||||
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
|
||||
|
||||
@ -666,34 +702,59 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
|
||||
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
|
||||
unsigned long flags;
|
||||
bool skip_beacon = false;
|
||||
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
|
||||
ath9k_cache_beacon_config(sc, bss_conf);
|
||||
ath9k_set_beacon(sc);
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
} else {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Take care of multiple interfaces when
|
||||
* enabling/disabling SWBA.
|
||||
*/
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (!bss_conf->enable_beacon &&
|
||||
(sc->nbcnvifs <= 1)) {
|
||||
cur_conf->enable_beacon = false;
|
||||
} else if (bss_conf->enable_beacon) {
|
||||
cur_conf->enable_beacon = true;
|
||||
ath9k_cache_beacon_config(sc, bss_conf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the HW beacon registers only when we have a valid
|
||||
* beacon interval.
|
||||
*/
|
||||
if (cur_conf->beacon_interval) {
|
||||
/*
|
||||
* Take care of multiple interfaces when
|
||||
* enabling/disabling SWBA.
|
||||
* If we are joining an existing IBSS network, start beaconing
|
||||
* only after a TSF-sync has taken place. Ensure that this
|
||||
* happens by setting the appropriate flags.
|
||||
*/
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (!bss_conf->enable_beacon &&
|
||||
(sc->nbcnvifs <= 1)) {
|
||||
cur_conf->enable_beacon = false;
|
||||
} else if (bss_conf->enable_beacon) {
|
||||
cur_conf->enable_beacon = true;
|
||||
ath9k_cache_beacon_config(sc, bss_conf);
|
||||
}
|
||||
}
|
||||
|
||||
if (cur_conf->beacon_interval) {
|
||||
if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator &&
|
||||
bss_conf->enable_beacon) {
|
||||
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||
skip_beacon = true;
|
||||
} else {
|
||||
ath9k_set_beacon(sc);
|
||||
|
||||
if (cur_conf->enable_beacon)
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
else
|
||||
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not set the SC_OP_BEACONS flag for IBSS joiner mode
|
||||
* here, it is done in ath9k_beacon_config_adhoc().
|
||||
*/
|
||||
if (cur_conf->enable_beacon && !skip_beacon)
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
else
|
||||
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,28 +320,25 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_node *an;
|
||||
u8 density;
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
an->sc = sc;
|
||||
an->sta = sta;
|
||||
an->vif = vif;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
ath_tx_node_init(sc, an);
|
||||
ath_tx_node_init(sc, an);
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
an->mpdudensity = density;
|
||||
an->mpdudensity = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
||||
ath_tx_node_cleanup(sc, an);
|
||||
ath_tx_node_cleanup(sc, an);
|
||||
}
|
||||
|
||||
void ath9k_tasklet(unsigned long data)
|
||||
|
@ -1204,7 +1204,7 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||
caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
|
||||
else if (sta->ht_cap.mcs.rx_mask[1])
|
||||
caps |= WLAN_RC_DS_FLAG;
|
||||
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
|
||||
if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
|
||||
caps |= WLAN_RC_40_FLAG;
|
||||
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
|
||||
caps |= WLAN_RC_SGI_FLAG;
|
||||
|
@ -533,7 +533,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
|
||||
if (sc->ps_flags & PS_BEACON_SYNC) {
|
||||
sc->ps_flags &= ~PS_BEACON_SYNC;
|
||||
ath_dbg(common, PS,
|
||||
"Reconfigure Beacon timers based on timestamp from the AP\n");
|
||||
"Reconfigure beacon timers based on synchronized timestamp\n");
|
||||
ath9k_set_beacon(sc);
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1233,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
* in HT IBSS when a beacon with HT-info is received after the station
|
||||
* has already been added.
|
||||
*/
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
@ -1904,8 +1904,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_buf *bf;
|
||||
u8 tidno;
|
||||
|
||||
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
|
||||
ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
tidno = ieee80211_get_qos_ctl(hdr)[0] &
|
||||
IEEE80211_QOS_CTL_TID_MASK;
|
||||
tid = ATH_AN_2_TID(txctl->an, tidno);
|
||||
|
@ -1853,7 +1853,7 @@ void *carl9170_alloc(size_t priv_size)
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
|
||||
IEEE80211_HW_SIGNAL_DBM;
|
||||
|
||||
if (!modparam_noht) {
|
||||
|
@ -341,7 +341,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
|
||||
}
|
||||
|
||||
out:
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
if (bss) {
|
||||
wil_dbg_wmi(wil, "Added BSS %pM\n",
|
||||
rx_mgmt_frame->bssid);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
} else {
|
||||
wil_err(wil, "cfg80211_inform_bss() failed\n");
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ brcmfmac-objs += \
|
||||
wl_cfg80211.o \
|
||||
fwil.o \
|
||||
fweh.o \
|
||||
p2p.o \
|
||||
dhd_cdc.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o
|
||||
@ -37,4 +38,4 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
|
||||
usb.o
|
||||
brcmfmac-$(CONFIG_BRCMDBG) += \
|
||||
dhd_dbg.o
|
||||
dhd_dbg.o
|
||||
|
@ -72,6 +72,7 @@
|
||||
#define BRCMF_C_SET_WSEC 134
|
||||
#define BRCMF_C_GET_PHY_NOISE 135
|
||||
#define BRCMF_C_GET_BSS_INFO 136
|
||||
#define BRCMF_C_SET_SCB_TIMEOUT 158
|
||||
#define BRCMF_C_GET_PHYLIST 180
|
||||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
||||
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
|
||||
@ -149,6 +150,7 @@
|
||||
#define BRCMF_E_REASON_MINTXRATE 9
|
||||
#define BRCMF_E_REASON_TXFAIL 10
|
||||
|
||||
#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4
|
||||
#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
|
||||
#define BRCMF_E_REASON_DIRECTED_ROAM 6
|
||||
#define BRCMF_E_REASON_TSPEC_REJECTED 7
|
||||
@ -375,6 +377,28 @@ struct brcmf_join_params {
|
||||
struct brcmf_assoc_params_le params_le;
|
||||
};
|
||||
|
||||
/* scan params for extended join */
|
||||
struct brcmf_join_scan_params_le {
|
||||
u8 scan_type; /* 0 use default, active or passive scan */
|
||||
__le32 nprobes; /* -1 use default, nr of probes per channel */
|
||||
__le32 active_time; /* -1 use default, dwell time per channel for
|
||||
* active scanning
|
||||
*/
|
||||
__le32 passive_time; /* -1 use default, dwell time per channel
|
||||
* for passive scanning
|
||||
*/
|
||||
__le32 home_time; /* -1 use default, dwell time for the home
|
||||
* channel between channel scans
|
||||
*/
|
||||
};
|
||||
|
||||
/* extended join params */
|
||||
struct brcmf_ext_join_params_le {
|
||||
struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */
|
||||
struct brcmf_join_scan_params_le scan_le;
|
||||
struct brcmf_assoc_params_le assoc_le;
|
||||
};
|
||||
|
||||
struct brcmf_wsec_key {
|
||||
u32 index; /* key index */
|
||||
u32 len; /* key length */
|
||||
@ -451,6 +475,19 @@ struct brcmf_sta_info_le {
|
||||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
};
|
||||
|
||||
/*
|
||||
* WLC_E_PROBRESP_MSG
|
||||
* WLC_E_P2P_PROBREQ_MSG
|
||||
* WLC_E_ACTION_FRAME_RX
|
||||
*/
|
||||
struct brcmf_rx_mgmt_data {
|
||||
__be16 version;
|
||||
__be16 chanspec;
|
||||
__be32 rssi;
|
||||
__be32 mactime;
|
||||
__be32 rate;
|
||||
};
|
||||
|
||||
/* Bus independent dongle command */
|
||||
struct brcmf_dcmd {
|
||||
uint cmd; /* common dongle cmd definition */
|
||||
@ -489,9 +526,6 @@ struct brcmf_pub {
|
||||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
|
||||
struct brcmf_fweh_info fweh;
|
||||
#ifdef DEBUG
|
||||
struct dentry *dbgfs_dir;
|
||||
@ -515,9 +549,11 @@ struct brcmf_cfg80211_vif;
|
||||
* @vif: points to cfg80211 specific interface information.
|
||||
* @ndev: associated network device.
|
||||
* @stats: interface specific network statistics.
|
||||
* @idx: interface index in device firmware.
|
||||
* @ifidx: interface index in device firmware.
|
||||
* @bssidx: index of bss associated with this interface.
|
||||
* @mac_addr: assigned mac address.
|
||||
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
|
||||
* @pend_8021x_wait: used for signalling change in count.
|
||||
*/
|
||||
struct brcmf_if {
|
||||
struct brcmf_pub *drvr;
|
||||
@ -526,9 +562,11 @@ struct brcmf_if {
|
||||
struct net_device_stats stats;
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
int idx;
|
||||
int ifidx;
|
||||
s32 bssidx;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
};
|
||||
|
||||
|
||||
@ -547,9 +585,10 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
struct sk_buff *rxp);
|
||||
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
|
||||
s32 bssidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
|
||||
s32 ifidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
|
||||
extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);
|
||||
|
||||
#endif /* _BRCMF_H_ */
|
||||
|
@ -24,18 +24,6 @@ enum brcmf_bus_state {
|
||||
BRCMF_BUS_DATA /* Ready for frame transfers */
|
||||
};
|
||||
|
||||
struct dngl_stats {
|
||||
unsigned long rx_packets; /* total packets received */
|
||||
unsigned long tx_packets; /* total packets transmitted */
|
||||
unsigned long rx_bytes; /* total bytes received */
|
||||
unsigned long tx_bytes; /* total bytes transmitted */
|
||||
unsigned long rx_errors; /* bad packets received */
|
||||
unsigned long tx_errors; /* packet transmit problems */
|
||||
unsigned long rx_dropped; /* packets dropped by dongle */
|
||||
unsigned long tx_dropped; /* packets dropped by dongle */
|
||||
unsigned long multicast; /* multicast packets received */
|
||||
};
|
||||
|
||||
struct brcmf_bus_dcmd {
|
||||
char *name;
|
||||
char *param;
|
||||
@ -72,11 +60,12 @@ struct brcmf_bus_ops {
|
||||
* @drvr: public driver information.
|
||||
* @state: operational state of the bus interface.
|
||||
* @maxctl: maximum size for rxctl request message.
|
||||
* @drvr_up: indicates driver up/down status.
|
||||
* @tx_realloc: number of tx packets realloced for headroom.
|
||||
* @dstats: dongle-based statistical data.
|
||||
* @align: alignment requirement for the bus.
|
||||
* @dcmd_list: bus/device specific dongle initialization commands.
|
||||
* @chip: device identifier of the dongle chip.
|
||||
* @chiprev: revision of the dongle chip.
|
||||
*/
|
||||
struct brcmf_bus {
|
||||
union {
|
||||
@ -87,10 +76,10 @@ struct brcmf_bus {
|
||||
struct brcmf_pub *drvr;
|
||||
enum brcmf_bus_state state;
|
||||
uint maxctl;
|
||||
bool drvr_up;
|
||||
unsigned long tx_realloc;
|
||||
struct dngl_stats dstats;
|
||||
u8 align;
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
struct list_head dcmd_list;
|
||||
|
||||
struct brcmf_bus_ops *ops;
|
||||
|
@ -303,6 +303,14 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
|
||||
return -EBADE;
|
||||
}
|
||||
/* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
* events this is easy because it contains the bssidx which maps
|
||||
* 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
* bssidx 1 is used for p2p0 and no data can be received or
|
||||
* transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
*/
|
||||
if (*ifidx)
|
||||
(*ifidx)++;
|
||||
|
||||
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
|
||||
BDC_PROTO_VER) {
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_proto.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fwil_types.h"
|
||||
#include "p2p.h"
|
||||
#include "wl_cfg80211.h"
|
||||
#include "fwil.h"
|
||||
|
||||
@ -40,6 +42,12 @@ MODULE_LICENSE("Dual BSD/GPL");
|
||||
int brcmf_msg_level;
|
||||
module_param(brcmf_msg_level, int, 0);
|
||||
|
||||
/* P2P0 enable */
|
||||
static int brcmf_p2p_enable;
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
module_param_named(p2pon, brcmf_p2p_enable, int, 0);
|
||||
MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
|
||||
#endif
|
||||
|
||||
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
|
||||
{
|
||||
@ -70,9 +78,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
|
||||
u32 buflen;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, multicast_work);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* Determine initial value of allmulti flag */
|
||||
@ -129,9 +138,10 @@ _brcmf_set_mac_address(struct work_struct *work)
|
||||
struct brcmf_if *ifp;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, setmacaddr_work);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
ETH_ALEN);
|
||||
if (err < 0) {
|
||||
@ -168,7 +178,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct ethhdr *eh;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* Can the device send data? */
|
||||
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
|
||||
@ -179,8 +189,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!drvr->iflist[ifp->idx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->idx);
|
||||
if (!drvr->iflist[ifp->bssidx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->bssidx);
|
||||
netif_stop_queue(ndev);
|
||||
dev_kfree_skb(skb);
|
||||
ret = -ENODEV;
|
||||
@ -192,14 +202,14 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct sk_buff *skb2;
|
||||
|
||||
brcmf_dbg(INFO, "%s: insufficient headroom\n",
|
||||
brcmf_ifname(drvr, ifp->idx));
|
||||
brcmf_ifname(drvr, ifp->bssidx));
|
||||
drvr->bus_if->tx_realloc++;
|
||||
skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
|
||||
dev_kfree_skb(skb);
|
||||
skb = skb2;
|
||||
if (skb == NULL) {
|
||||
brcmf_err("%s: skb_realloc_headroom failed\n",
|
||||
brcmf_ifname(drvr, ifp->idx));
|
||||
brcmf_ifname(drvr, ifp->bssidx));
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
@ -217,19 +227,21 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
if (is_multicast_ether_addr(eh->h_dest))
|
||||
drvr->tx_multicast++;
|
||||
if (ntohs(eh->h_proto) == ETH_P_PAE)
|
||||
atomic_inc(&drvr->pend_8021x_cnt);
|
||||
atomic_inc(&ifp->pend_8021x_cnt);
|
||||
|
||||
/* If the protocol uses a data header, apply it */
|
||||
brcmf_proto_hdrpush(drvr, ifp->idx, skb);
|
||||
brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);
|
||||
|
||||
/* Use bus module to send data frame */
|
||||
ret = brcmf_bus_txdata(drvr->bus_if, skb);
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
drvr->bus_if->dstats.tx_dropped++;
|
||||
else
|
||||
drvr->bus_if->dstats.tx_packets++;
|
||||
if (ret) {
|
||||
ifp->stats.tx_dropped++;
|
||||
} else {
|
||||
ifp->stats.tx_packets++;
|
||||
ifp->stats.tx_bytes += skb->len;
|
||||
}
|
||||
|
||||
/* Return ok: we always eat the packet */
|
||||
return NETDEV_TX_OK;
|
||||
@ -270,12 +282,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
skb_queue_walk_safe(skb_list, skb, pnext) {
|
||||
skb_unlink(skb, skb_list);
|
||||
|
||||
/* process and remove protocol-specific header
|
||||
*/
|
||||
/* process and remove protocol-specific header */
|
||||
ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENODATA)
|
||||
bus_if->dstats.rx_errors++;
|
||||
ifp = drvr->iflist[ifidx];
|
||||
|
||||
if (ret || !ifp || !ifp->ndev) {
|
||||
if ((ret != -ENODATA) && ifp)
|
||||
ifp->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
@ -295,21 +308,11 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
eth = skb->data;
|
||||
len = skb->len;
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
if (ifp == NULL)
|
||||
ifp = drvr->iflist[0];
|
||||
|
||||
if (!ifp || !ifp->ndev ||
|
||||
ifp->ndev->reg_state != NETREG_REGISTERED) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb->dev = ifp->ndev;
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
bus_if->dstats.multicast++;
|
||||
ifp->stats.multicast++;
|
||||
|
||||
skb->data = eth;
|
||||
skb->len = len;
|
||||
@ -325,8 +328,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
ifp->ndev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
bus_if->dstats.rx_bytes += skb->len;
|
||||
bus_if->dstats.rx_packets++; /* Local count */
|
||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
ifp->stats.rx_bytes += skb->len;
|
||||
ifp->stats.rx_packets++;
|
||||
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
@ -348,36 +356,31 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
|
||||
u16 type;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_proto_hdrpull(drvr, &ifidx, txp);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
if (!ifp)
|
||||
return;
|
||||
|
||||
eh = (struct ethhdr *)(txp->data);
|
||||
type = ntohs(eh->h_proto);
|
||||
|
||||
if (type == ETH_P_PAE) {
|
||||
atomic_dec(&drvr->pend_8021x_cnt);
|
||||
if (waitqueue_active(&drvr->pend_8021x_wait))
|
||||
wake_up(&drvr->pend_8021x_wait);
|
||||
atomic_dec(&ifp->pend_8021x_cnt);
|
||||
if (waitqueue_active(&ifp->pend_8021x_wait))
|
||||
wake_up(&ifp->pend_8021x_wait);
|
||||
}
|
||||
if (!success)
|
||||
ifp->stats.tx_errors++;
|
||||
}
|
||||
|
||||
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_bus *bus_if = ifp->drvr->bus_if;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Copy dongle stats to net device stats */
|
||||
ifp->stats.rx_packets = bus_if->dstats.rx_packets;
|
||||
ifp->stats.tx_packets = bus_if->dstats.tx_packets;
|
||||
ifp->stats.rx_bytes = bus_if->dstats.rx_bytes;
|
||||
ifp->stats.tx_bytes = bus_if->dstats.tx_bytes;
|
||||
ifp->stats.rx_errors = bus_if->dstats.rx_errors;
|
||||
ifp->stats.tx_errors = bus_if->dstats.tx_errors;
|
||||
ifp->stats.rx_dropped = bus_if->dstats.rx_dropped;
|
||||
ifp->stats.tx_dropped = bus_if->dstats.tx_dropped;
|
||||
ifp->stats.multicast = bus_if->dstats.multicast;
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
return &ifp->stats;
|
||||
}
|
||||
@ -431,7 +434,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
||||
u32 toe_cmpnt, csum_dir;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* all ethtool calls start with a cmd word */
|
||||
if (copy_from_user(&cmd, uaddr, sizeof(u32)))
|
||||
@ -454,13 +457,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
||||
sprintf(info.driver, "dhd");
|
||||
strcpy(info.version, BRCMF_VERSION_STR);
|
||||
}
|
||||
|
||||
/* otherwise, require dongle to be up */
|
||||
else if (!drvr->bus_if->drvr_up) {
|
||||
brcmf_err("dongle is not up\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* finally, report dongle driver type */
|
||||
/* report dongle driver type */
|
||||
else
|
||||
sprintf(info.driver, "wl");
|
||||
|
||||
@ -534,9 +531,9 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);
|
||||
|
||||
if (!drvr->iflist[ifp->idx])
|
||||
if (!drvr->iflist[ifp->bssidx])
|
||||
return -1;
|
||||
|
||||
if (cmd == SIOCETHTOOL)
|
||||
@ -548,17 +545,12 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
||||
static int brcmf_netdev_stop(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (drvr->bus_if->drvr_up == 0)
|
||||
return 0;
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
brcmf_cfg80211_down(ndev);
|
||||
|
||||
/* Set state and stop OS transmissions */
|
||||
drvr->bus_if->drvr_up = false;
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
return 0;
|
||||
@ -572,7 +564,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
u32 toe_ol;
|
||||
s32 ret = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* If bus is not ready, can't continue */
|
||||
if (bus_if->state != BRCMF_BUS_DATA) {
|
||||
@ -580,9 +572,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
atomic_set(&drvr->pend_8021x_cnt, 0);
|
||||
|
||||
memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
|
||||
atomic_set(&ifp->pend_8021x_cnt, 0);
|
||||
|
||||
/* Get current TOE mode from dongle */
|
||||
if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
|
||||
@ -593,7 +583,6 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
|
||||
/* Allow transmit calls */
|
||||
netif_start_queue(ndev);
|
||||
drvr->bus_if->drvr_up = true;
|
||||
if (brcmf_cfg80211_up(ndev)) {
|
||||
brcmf_err("failed to bring up cfg80211\n");
|
||||
return -1;
|
||||
@ -612,29 +601,18 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
|
||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_virt = {
|
||||
.ndo_open = brcmf_cfg80211_up,
|
||||
.ndo_stop = brcmf_cfg80211_down,
|
||||
.ndo_get_stats = brcmf_netdev_get_stats,
|
||||
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
|
||||
.ndo_start_xmit = brcmf_netdev_start_xmit,
|
||||
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
|
||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct net_device *ndev;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
|
||||
ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* set appropriate operations */
|
||||
if (!ifp->idx)
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
else
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_virt;
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
|
||||
ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
|
||||
ndev->ethtool_ops = &brcmf_ethtool_ops;
|
||||
@ -645,7 +623,14 @@ int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (rtnl_locked)
|
||||
err = register_netdevice(ndev);
|
||||
else
|
||||
err = register_netdev(ndev);
|
||||
if (err != 0) {
|
||||
brcmf_err("couldn't register the net device\n");
|
||||
goto fail;
|
||||
}
|
||||
@ -659,16 +644,78 @@ fail:
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
char *name, u8 *addr_mask)
|
||||
static int brcmf_net_p2p_open(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
return brcmf_cfg80211_up(ndev);
|
||||
}
|
||||
|
||||
static int brcmf_net_p2p_stop(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
return brcmf_cfg80211_down(ndev);
|
||||
}
|
||||
|
||||
static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
|
||||
struct ifreq *ifr, int cmd)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_p2p = {
|
||||
.ndo_open = brcmf_net_p2p_open,
|
||||
.ndo_stop = brcmf_net_p2p_stop,
|
||||
.ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
|
||||
.ndo_start_xmit = brcmf_net_p2p_start_xmit
|
||||
};
|
||||
|
||||
static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
|
||||
ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_p2p;
|
||||
|
||||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
brcmf_err("couldn't register the p2p net device\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
char *name, u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct net_device *ndev;
|
||||
int i;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
ifp = drvr->iflist[bssidx];
|
||||
/*
|
||||
* Delete the existing interface before overwriting it
|
||||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
@ -680,7 +727,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
} else {
|
||||
brcmf_err("ignore IF event\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
@ -697,16 +744,15 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
ifp = netdev_priv(ndev);
|
||||
ifp->ndev = ndev;
|
||||
ifp->drvr = drvr;
|
||||
drvr->iflist[ifidx] = ifp;
|
||||
ifp->idx = ifidx;
|
||||
drvr->iflist[bssidx] = ifp;
|
||||
ifp->ifidx = ifidx;
|
||||
ifp->bssidx = bssidx;
|
||||
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (addr_mask != NULL)
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
|
||||
init_waitqueue_head(&ifp->pend_8021x_wait);
|
||||
|
||||
if (mac_addr != NULL)
|
||||
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||
|
||||
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
||||
current->pid, ifp->ndev->name, ifp->mac_addr);
|
||||
@ -714,19 +760,18 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
return ifp;
|
||||
}
|
||||
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
ifp = drvr->iflist[bssidx];
|
||||
if (!ifp) {
|
||||
brcmf_err("Null interface\n");
|
||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||
return;
|
||||
}
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
|
||||
if (ifp->ndev) {
|
||||
if (ifidx == 0) {
|
||||
if (bssidx == 0) {
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
rtnl_lock();
|
||||
brcmf_netdev_stop(ifp->ndev);
|
||||
@ -736,12 +781,14 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
||||
netif_stop_queue(ifp->ndev);
|
||||
}
|
||||
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
unregister_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
if (ifidx == 0)
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
if (bssidx == 0)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(ifp->ndev);
|
||||
}
|
||||
@ -781,8 +828,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||
|
||||
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
|
||||
|
||||
init_waitqueue_head(&drvr->pend_8021x_wait);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
@ -797,6 +842,7 @@ int brcmf_bus_start(struct device *dev)
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
@ -812,6 +858,13 @@ int brcmf_bus_start(struct device *dev)
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
if (brcmf_p2p_enable)
|
||||
p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
|
||||
else
|
||||
p2p_ifp = NULL;
|
||||
if (IS_ERR(p2p_ifp))
|
||||
p2p_ifp = NULL;
|
||||
|
||||
/* signal bus ready */
|
||||
bus_if->state = BRCMF_BUS_DATA;
|
||||
|
||||
@ -830,16 +883,22 @@ int brcmf_bus_start(struct device *dev)
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = brcmf_net_attach(ifp);
|
||||
ret = brcmf_net_attach(ifp, false);
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
brcmf_err("failed: %d\n", ret);
|
||||
if (drvr->config)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(drvr->iflist[0]->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
if (p2p_ifp) {
|
||||
free_netdev(p2p_ifp->ndev);
|
||||
drvr->iflist[1] = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if ((brcmf_p2p_enable) && (p2p_ifp))
|
||||
brcmf_net_p2p_attach(p2p_ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -865,12 +924,13 @@ void brcmf_dev_reset(struct device *dev)
|
||||
if (drvr == NULL)
|
||||
return;
|
||||
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
if (drvr->iflist[0])
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
}
|
||||
|
||||
void brcmf_detach(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
s32 i;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
@ -897,19 +957,18 @@ void brcmf_detach(struct device *dev)
|
||||
kfree(drvr);
|
||||
}
|
||||
|
||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
|
||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
|
||||
{
|
||||
return atomic_read(&drvr->pend_8021x_cnt);
|
||||
return atomic_read(&ifp->pend_8021x_cnt);
|
||||
}
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
int err;
|
||||
|
||||
err = wait_event_timeout(drvr->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(drvr),
|
||||
err = wait_event_timeout(ifp->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(ifp),
|
||||
msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
|
||||
|
||||
WARN_ON(!err);
|
||||
@ -917,6 +976,16 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||
return !err;
|
||||
}
|
||||
|
||||
/*
|
||||
* return chip id and rev of the device encoded in u32.
|
||||
*/
|
||||
u32 brcmf_get_chip_info(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_bus *bus = ifp->drvr->bus_if;
|
||||
|
||||
return bus->chip << 4 | bus->chiprev;
|
||||
}
|
||||
|
||||
static void brcmf_driver_init(struct work_struct *work)
|
||||
{
|
||||
brcmf_debugfs_init();
|
||||
|
@ -1096,7 +1096,6 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||
if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
|
||||
type != BRCMF_SDIO_FT_SUPER) {
|
||||
brcmf_err("HW header length too long\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
rd->len = 0;
|
||||
@ -1298,7 +1297,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||
if (errcode < 0) {
|
||||
brcmf_err("glom read of %d bytes failed: %d\n",
|
||||
dlen, errcode);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (bus->glomerr++ < 3) {
|
||||
@ -1477,7 +1475,6 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
||||
if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
|
||||
brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
|
||||
rdlen, bus->sdiodev->bus_if->maxctl);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
goto done;
|
||||
}
|
||||
@ -1485,7 +1482,6 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
||||
if ((len - doff) > bus->sdiodev->bus_if->maxctl) {
|
||||
brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
|
||||
len, len - doff, bus->sdiodev->bus_if->maxctl);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
goto done;
|
||||
@ -1633,7 +1629,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||
if (!pkt) {
|
||||
/* Give up on data, request rtx of events */
|
||||
brcmf_err("brcmu_pkt_buf_get_skb failed\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_dropped++;
|
||||
brcmf_sdbrcm_rxfail(bus, false,
|
||||
RETRYCHAN(rd->channel));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
@ -1651,7 +1646,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||
brcmf_err("read %d bytes from channel %d failed: %d\n",
|
||||
rd->len, rd->channel, sdret);
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_rxfail(bus, true,
|
||||
RETRYCHAN(rd->channel));
|
||||
@ -1939,10 +1933,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
||||
datalen = pkt->len - SDPCM_HDRLEN;
|
||||
|
||||
ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
|
||||
if (ret)
|
||||
bus->sdiodev->bus_if->dstats.tx_errors++;
|
||||
else
|
||||
bus->sdiodev->bus_if->dstats.tx_bytes += datalen;
|
||||
|
||||
/* In poll mode, need to check for other events */
|
||||
if (!bus->intr && cnt) {
|
||||
@ -1961,8 +1951,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
||||
}
|
||||
|
||||
/* Deflow-control stack if needed */
|
||||
if (bus->sdiodev->bus_if->drvr_up &&
|
||||
(bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
|
||||
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
|
||||
bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
|
||||
bus->txoff = false;
|
||||
brcmf_txflowblock(bus->sdiodev->dev, false);
|
||||
@ -2709,9 +2698,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||
* address of sdpcm_shared structure
|
||||
*/
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
|
||||
(u8 *)&addr_le, 4);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2730,10 +2720,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
||||
}
|
||||
|
||||
/* Read hndrte_shared structure */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
|
||||
sizeof(struct sdpcm_shared_le));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -2835,14 +2823,12 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
||||
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
||||
sizeof(struct brcmf_trap_info));
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
|
||||
@ -3307,9 +3293,6 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bus->sdiodev->bus_if->drvr_up)
|
||||
return -EISCONN;
|
||||
|
||||
ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
|
||||
&bus->sdiodev->func[2]->dev);
|
||||
if (ret) {
|
||||
@ -3940,6 +3923,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
||||
/* Assign bus interface call back */
|
||||
bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
|
||||
bus->sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
|
||||
bus->sdiodev->bus_if->chip = bus->ci->chip;
|
||||
bus->sdiodev->bus_if->chiprev = bus->ci->chiprev;
|
||||
|
||||
/* Attach to the brcmf/OS/network interface */
|
||||
ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev);
|
||||
|
@ -189,24 +189,24 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->ifidx];
|
||||
ifp = drvr->iflist[ifevent->bssidx];
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||
emsg->addr);
|
||||
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
|
||||
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
|
||||
emsg->ifname, emsg->addr);
|
||||
if (IS_ERR(ifp))
|
||||
return;
|
||||
|
||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||
err = brcmf_net_attach(ifp);
|
||||
err = brcmf_net_attach(ifp, false);
|
||||
}
|
||||
|
||||
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_DEL)
|
||||
brcmf_del_if(drvr, ifevent->ifidx);
|
||||
brcmf_del_if(drvr, ifevent->bssidx);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,8 +250,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||
drvr = container_of(fweh, struct brcmf_pub, fweh);
|
||||
|
||||
while ((event = brcmf_fweh_dequeue_event(fweh))) {
|
||||
ifp = drvr->iflist[event->ifidx];
|
||||
|
||||
brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
|
||||
brcmf_fweh_event_name(event->code), event->code,
|
||||
event->emsg.ifidx, event->emsg.bsscfgidx,
|
||||
@ -283,6 +281,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
||||
goto event_free;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[emsg.bsscfgidx];
|
||||
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||
event->data);
|
||||
if (err) {
|
||||
|
@ -83,6 +83,7 @@ struct brcmf_event;
|
||||
BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
|
||||
BRCMF_ENUM_DEF(TRACE, 52) \
|
||||
BRCMF_ENUM_DEF(IF, 54) \
|
||||
BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
|
||||
BRCMF_ENUM_DEF(RSSI, 56) \
|
||||
BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
|
||||
BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
|
||||
@ -96,8 +97,11 @@ struct brcmf_event;
|
||||
BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
|
||||
BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
|
||||
BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \
|
||||
BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
|
||||
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74)
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75)
|
||||
|
||||
#define BRCMF_ENUM_DEF(id, val) \
|
||||
BRCMF_E_##id = (val),
|
||||
|
@ -45,9 +45,10 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
|
||||
if (data != NULL)
|
||||
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
|
||||
if (set)
|
||||
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
|
||||
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data,
|
||||
len);
|
||||
else
|
||||
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
|
||||
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data,
|
||||
len);
|
||||
|
||||
if (err >= 0)
|
||||
@ -100,6 +101,7 @@ brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
|
||||
__le32 data_le = cpu_to_le32(data);
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
@ -116,6 +118,7 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
*data = le32_to_cpu(data_le);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
66
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
Normal file
66
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FWIL_TYPES_H_
|
||||
#define FWIL_TYPES_H_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
|
||||
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
|
||||
|
||||
|
||||
enum brcmf_fil_p2p_if_types {
|
||||
BRCMF_FIL_P2P_IF_CLIENT,
|
||||
BRCMF_FIL_P2P_IF_GO,
|
||||
BRCMF_FIL_P2P_IF_DYNBCN_GO,
|
||||
BRCMF_FIL_P2P_IF_DEV,
|
||||
};
|
||||
|
||||
struct brcmf_fil_p2p_if_le {
|
||||
u8 addr[ETH_ALEN];
|
||||
__le16 type;
|
||||
__le16 chspec;
|
||||
};
|
||||
|
||||
struct brcmf_fil_chan_info_le {
|
||||
__le32 hw_channel;
|
||||
__le32 target_channel;
|
||||
__le32 scan_channel;
|
||||
};
|
||||
|
||||
struct brcmf_fil_action_frame_le {
|
||||
u8 da[ETH_ALEN];
|
||||
__le16 len;
|
||||
__le32 packet_id;
|
||||
u8 data[BRCMF_FIL_ACTION_FRAME_SIZE];
|
||||
};
|
||||
|
||||
struct brcmf_fil_af_params_le {
|
||||
__le32 channel;
|
||||
__le32 dwell_time;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pad[2];
|
||||
struct brcmf_fil_action_frame_le action_frame;
|
||||
};
|
||||
|
||||
struct brcmf_fil_bss_enable_le {
|
||||
__le32 bsscfg_idx;
|
||||
__le32 enable;
|
||||
};
|
||||
|
||||
#endif /* FWIL_TYPES_H_ */
|
2277
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Normal file
2277
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
Normal file
File diff suppressed because it is too large
Load Diff
183
drivers/net/wireless/brcm80211/brcmfmac/p2p.h
Normal file
183
drivers/net/wireless/brcm80211/brcmfmac/p2p.h
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Broadcom Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef WL_CFGP2P_H_
|
||||
#define WL_CFGP2P_H_
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
struct brcmf_cfg80211_info;
|
||||
|
||||
/**
|
||||
* enum p2p_bss_type - different type of BSS configurations.
|
||||
*
|
||||
* @P2PAPI_BSSCFG_PRIMARY: maps to driver's primary bsscfg.
|
||||
* @P2PAPI_BSSCFG_DEVICE: maps to driver's P2P device discovery bsscfg.
|
||||
* @P2PAPI_BSSCFG_CONNECTION: maps to driver's P2P connection bsscfg.
|
||||
* @P2PAPI_BSSCFG_MAX: used for range checking.
|
||||
*/
|
||||
enum p2p_bss_type {
|
||||
P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
|
||||
P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
|
||||
P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */
|
||||
P2PAPI_BSSCFG_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_bss - peer-to-peer bss related information.
|
||||
*
|
||||
* @vif: virtual interface of this P2P bss.
|
||||
* @private_data: TBD
|
||||
*/
|
||||
struct p2p_bss {
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum brcmf_p2p_status - P2P specific dongle status.
|
||||
*
|
||||
* @BRCMF_P2P_STATUS_IF_ADD: peer-to-peer vif add sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_DEL: NOT-USED?
|
||||
* @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
|
||||
* @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
|
||||
* @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
|
||||
* @BRCMF_P2P_STATUS_SENDING_ACT_FRAME: In the process of sending action frame.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN: extra listen time for af tx.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME: waiting for action frame response.
|
||||
* @BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL: search channel for AF active.
|
||||
*/
|
||||
enum brcmf_p2p_status {
|
||||
BRCMF_P2P_STATUS_ENABLED,
|
||||
BRCMF_P2P_STATUS_IF_ADD,
|
||||
BRCMF_P2P_STATUS_IF_DEL,
|
||||
BRCMF_P2P_STATUS_IF_DELETING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_NOACK,
|
||||
BRCMF_P2P_STATUS_GO_NEG_PHASE,
|
||||
BRCMF_P2P_STATUS_DISCOVER_LISTEN,
|
||||
BRCMF_P2P_STATUS_SENDING_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL
|
||||
};
|
||||
|
||||
/**
|
||||
* struct afx_hdl - action frame off channel storage.
|
||||
*
|
||||
* @afx_work: worker thread for searching channel
|
||||
* @act_frm_scan: thread synchronizing struct.
|
||||
* @is_active: channel searching active.
|
||||
* @peer_chan: current channel.
|
||||
* @is_listen: sets mode for afx worker.
|
||||
* @my_listen_chan: this peers listen channel.
|
||||
* @peer_listen_chan: remote peers listen channel.
|
||||
* @tx_dst_addr: mac address where tx af should be sent to.
|
||||
*/
|
||||
struct afx_hdl {
|
||||
struct work_struct afx_work;
|
||||
struct completion act_frm_scan;
|
||||
bool is_active;
|
||||
s32 peer_chan;
|
||||
bool is_listen;
|
||||
u16 my_listen_chan;
|
||||
u16 peer_listen_chan;
|
||||
u8 tx_dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_p2p_info - p2p specific driver information.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
* @status: status of P2P (see enum brcmf_p2p_status).
|
||||
* @dev_addr: P2P device address.
|
||||
* @int_addr: P2P interface address.
|
||||
* @bss_idx: informate for P2P bss types.
|
||||
* @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @ssid: ssid for P2P GO.
|
||||
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @remain_on_channel: contains copy of struct used by cfg80211.
|
||||
* @remain_on_channel_cookie: cookie counter for remain on channel cmd
|
||||
* @next_af_subtype: expected action frame subtype.
|
||||
* @send_af_done: indication that action frame tx is complete.
|
||||
* @afx_hdl: action frame search handler info.
|
||||
* @af_sent_channel: channel action frame is sent.
|
||||
* @af_tx_sent_jiffies: jiffies time when af tx was transmitted.
|
||||
* @wait_next_af: thread synchronizing struct.
|
||||
* @gon_req_action: about to send go negotiation requets frame.
|
||||
* @block_gon_req_tx: drop tx go negotiation requets frame.
|
||||
*/
|
||||
struct brcmf_p2p_info {
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
unsigned long status;
|
||||
u8 dev_addr[ETH_ALEN];
|
||||
u8 int_addr[ETH_ALEN];
|
||||
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
|
||||
struct timer_list listen_timer;
|
||||
struct brcmf_ssid ssid;
|
||||
u8 listen_channel;
|
||||
struct ieee80211_channel remain_on_channel;
|
||||
u32 remain_on_channel_cookie;
|
||||
u8 next_af_subtype;
|
||||
struct completion send_af_done;
|
||||
struct afx_hdl afx_hdl;
|
||||
u32 af_sent_channel;
|
||||
unsigned long af_tx_sent_jiffies;
|
||||
struct completion wait_next_af;
|
||||
bool gon_req_action;
|
||||
bool block_gon_req_tx;
|
||||
};
|
||||
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
|
||||
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
||||
enum nl80211_iftype type, u32 *flags,
|
||||
struct vif_params *params);
|
||||
int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
|
||||
enum brcmf_fil_p2p_if_types if_type);
|
||||
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
||||
struct cfg80211_scan_request *request,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int duration, u64 *cookie);
|
||||
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
|
||||
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct brcmf_fil_af_params_le *af_params);
|
||||
bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bi);
|
||||
s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
#endif /* WL_CFGP2P_H_ */
|
@ -420,10 +420,6 @@ static void brcmf_usb_tx_complete(struct urb *urb)
|
||||
brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
|
||||
req->skb);
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
if (urb->status == 0)
|
||||
devinfo->bus_pub.bus->dstats.tx_packets++;
|
||||
else
|
||||
devinfo->bus_pub.bus->dstats.tx_errors++;
|
||||
|
||||
brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
|
||||
|
||||
@ -450,10 +446,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
||||
req->skb = NULL;
|
||||
|
||||
/* zero lenght packets indicate usb "failure". Do not refill */
|
||||
if (urb->status == 0 && urb->actual_length) {
|
||||
devinfo->bus_pub.bus->dstats.rx_packets++;
|
||||
} else {
|
||||
devinfo->bus_pub.bus->dstats.rx_errors++;
|
||||
if (urb->status != 0 || !urb->actual_length) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
|
||||
return;
|
||||
@ -1256,6 +1249,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
||||
bus->bus_priv.usb = bus_pub;
|
||||
dev_set_drvdata(dev, bus);
|
||||
bus->ops = &brcmf_usb_bus_ops;
|
||||
bus->chip = bus_pub->devid;
|
||||
bus->chiprev = bus_pub->chiprev;
|
||||
|
||||
/* Attach to the common driver interface */
|
||||
ret = brcmf_attach(0, dev);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,38 @@
|
||||
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
|
||||
#define IE_MAX_LEN 512
|
||||
|
||||
/* IE TLV processing */
|
||||
#define TLV_LEN_OFF 1 /* length offset */
|
||||
#define TLV_HDR_LEN 2 /* header length */
|
||||
#define TLV_BODY_OFF 2 /* body offset */
|
||||
#define TLV_OUI_LEN 3 /* oui id length */
|
||||
|
||||
/* 802.11 Mgmt Packet flags */
|
||||
#define BRCMF_VNDR_IE_BEACON_FLAG 0x1
|
||||
#define BRCMF_VNDR_IE_PRBRSP_FLAG 0x2
|
||||
#define BRCMF_VNDR_IE_ASSOCRSP_FLAG 0x4
|
||||
#define BRCMF_VNDR_IE_AUTHRSP_FLAG 0x8
|
||||
#define BRCMF_VNDR_IE_PRBREQ_FLAG 0x10
|
||||
#define BRCMF_VNDR_IE_ASSOCREQ_FLAG 0x20
|
||||
/* vendor IE in IW advertisement protocol ID field */
|
||||
#define BRCMF_VNDR_IE_IWAPID_FLAG 0x40
|
||||
/* allow custom IE id */
|
||||
#define BRCMF_VNDR_IE_CUSTOM_FLAG 0x100
|
||||
|
||||
/* P2P Action Frames flags (spec ordered) */
|
||||
#define BRCMF_VNDR_IE_GONREQ_FLAG 0x001000
|
||||
#define BRCMF_VNDR_IE_GONRSP_FLAG 0x002000
|
||||
#define BRCMF_VNDR_IE_GONCFM_FLAG 0x004000
|
||||
#define BRCMF_VNDR_IE_INVREQ_FLAG 0x008000
|
||||
#define BRCMF_VNDR_IE_INVRSP_FLAG 0x010000
|
||||
#define BRCMF_VNDR_IE_DISREQ_FLAG 0x020000
|
||||
#define BRCMF_VNDR_IE_DISRSP_FLAG 0x040000
|
||||
#define BRCMF_VNDR_IE_PRDREQ_FLAG 0x080000
|
||||
#define BRCMF_VNDR_IE_PRDRSP_FLAG 0x100000
|
||||
|
||||
#define BRCMF_VNDR_IE_P2PAF_SHIFT 12
|
||||
|
||||
|
||||
/**
|
||||
* enum brcmf_scan_status - dongle scan status
|
||||
*
|
||||
@ -52,11 +84,19 @@ enum brcmf_scan_status {
|
||||
BRCMF_SCAN_STATUS_ABORT,
|
||||
};
|
||||
|
||||
/* wi-fi mode */
|
||||
/**
|
||||
* enum wl_mode - driver mode of virtual interface.
|
||||
*
|
||||
* @WL_MODE_BSS: connects to BSS.
|
||||
* @WL_MODE_IBSS: operate as ad-hoc.
|
||||
* @WL_MODE_AP: operate as access-point.
|
||||
* @WL_MODE_P2P: provide P2P discovery.
|
||||
*/
|
||||
enum wl_mode {
|
||||
WL_MODE_BSS,
|
||||
WL_MODE_IBSS,
|
||||
WL_MODE_AP
|
||||
WL_MODE_AP,
|
||||
WL_MODE_P2P
|
||||
};
|
||||
|
||||
/* dongle configuration */
|
||||
@ -108,6 +148,7 @@ struct brcmf_cfg80211_profile {
|
||||
* @BRCMF_VIF_STATUS_READY: ready for operation.
|
||||
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
|
||||
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
|
||||
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
|
||||
*/
|
||||
@ -115,6 +156,7 @@ enum brcmf_vif_status {
|
||||
BRCMF_VIF_STATUS_READY,
|
||||
BRCMF_VIF_STATUS_CONNECTING,
|
||||
BRCMF_VIF_STATUS_CONNECTED,
|
||||
BRCMF_VIF_STATUS_DISCONNECTING,
|
||||
BRCMF_VIF_STATUS_AP_CREATING,
|
||||
BRCMF_VIF_STATUS_AP_CREATED
|
||||
};
|
||||
@ -122,16 +164,22 @@ enum brcmf_vif_status {
|
||||
/**
|
||||
* struct vif_saved_ie - holds saved IEs for a virtual interface.
|
||||
*
|
||||
* @probe_req_ie: IE info for probe request.
|
||||
* @probe_res_ie: IE info for probe response.
|
||||
* @beacon_ie: IE info for beacon frame.
|
||||
* @probe_req_ie_len: IE info length for probe request.
|
||||
* @probe_res_ie_len: IE info length for probe response.
|
||||
* @beacon_ie_len: IE info length for beacon frame.
|
||||
*/
|
||||
struct vif_saved_ie {
|
||||
u8 probe_req_ie[IE_MAX_LEN];
|
||||
u8 probe_res_ie[IE_MAX_LEN];
|
||||
u8 beacon_ie[IE_MAX_LEN];
|
||||
u8 assoc_req_ie[IE_MAX_LEN];
|
||||
u32 probe_req_ie_len;
|
||||
u32 probe_res_ie_len;
|
||||
u32 beacon_ie_len;
|
||||
u32 assoc_req_ie_len;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -145,6 +193,7 @@ struct vif_saved_ie {
|
||||
* @sme_state: SME state using enum brcmf_vif_status bits.
|
||||
* @pm_block: power-management blocked.
|
||||
* @list: linked list.
|
||||
* @mgmt_rx_reg: registered rx mgmt frame types.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif {
|
||||
struct brcmf_if *ifp;
|
||||
@ -156,6 +205,7 @@ struct brcmf_cfg80211_vif {
|
||||
bool pm_block;
|
||||
struct vif_saved_ie saved_ie;
|
||||
struct list_head list;
|
||||
u16 mgmt_rx_reg;
|
||||
};
|
||||
|
||||
/* association inform */
|
||||
@ -189,6 +239,9 @@ struct escan_info {
|
||||
u8 escan_buf[WL_ESCAN_BUF_SIZE];
|
||||
struct wiphy *wiphy;
|
||||
struct net_device *ndev;
|
||||
s32 (*run)(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct cfg80211_scan_request *request, u16 action);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -272,11 +325,28 @@ struct brcmf_pno_scanresults_le {
|
||||
__le32 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_vif_event - virtual interface event information.
|
||||
*
|
||||
* @vif_wq: waitqueue awaiting interface event from firmware.
|
||||
* @vif_event_lock: protects other members in this structure.
|
||||
* @vif_complete: completion for net attach.
|
||||
* @action: either add, change, or delete.
|
||||
* @vif: virtual interface object related to the event.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif_event {
|
||||
wait_queue_head_t vif_wq;
|
||||
struct mutex vif_event_lock;
|
||||
u8 action;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||
*
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @p2p: peer-to-peer specific information.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @usr_sync: mainly for dongle up/down synchronization.
|
||||
* @bss_list: bss_list holding scanned ap information.
|
||||
@ -304,10 +374,12 @@ struct brcmf_pno_scanresults_le {
|
||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @vif_list: linked list of vif instances.
|
||||
* @vif_cnt: number of vif instances.
|
||||
* @vif_event: vif event signalling.
|
||||
*/
|
||||
struct brcmf_cfg80211_info {
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct brcmf_p2p_info p2p;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct mutex usr_sync;
|
||||
struct brcmf_scan_results *bss_list;
|
||||
@ -335,6 +407,21 @@ struct brcmf_cfg80211_info {
|
||||
u8 *escan_ioctl_buf;
|
||||
struct list_head vif_list;
|
||||
u8 vif_cnt;
|
||||
struct brcmf_cfg80211_vif_event vif_event;
|
||||
struct completion vif_disabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_tlv - tag_ID/length/value_buffer tuple.
|
||||
*
|
||||
* @id: tag identifier.
|
||||
* @len: number of bytes in value buffer.
|
||||
* @data: value buffer.
|
||||
*/
|
||||
struct brcmf_tlv {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
|
||||
@ -389,4 +476,26 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||
s32 brcmf_cfg80211_up(struct net_device *ndev);
|
||||
s32 brcmf_cfg80211_down(struct net_device *ndev);
|
||||
|
||||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
enum nl80211_iftype type,
|
||||
bool pm_block);
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
|
||||
|
||||
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
|
||||
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
|
||||
u16 channel_to_chanspec(struct ieee80211_channel *ch);
|
||||
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
|
||||
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
|
||||
int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
|
||||
u8 action, ulong timeout);
|
||||
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
bool aborted, bool fw_abort);
|
||||
void brcmf_set_mpc(struct net_device *ndev, int mpc);
|
||||
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
|
||||
|
||||
#endif /* _wl_cfg80211_h_ */
|
||||
|
@ -183,8 +183,7 @@ static bool brcms_c_country_valid(const char *ccode)
|
||||
* chars.
|
||||
*/
|
||||
if (!((0x80 & ccode[0]) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
|
||||
(0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A &&
|
||||
ccode[2] == '\0'))
|
||||
(0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
@ -101,8 +101,6 @@
|
||||
#define DOT11_RTS_LEN 16
|
||||
#define DOT11_CTS_LEN 10
|
||||
#define DOT11_BA_BITMAP_LEN 128
|
||||
#define DOT11_MIN_BEACON_PERIOD 1
|
||||
#define DOT11_MAX_BEACON_PERIOD 0xFFFF
|
||||
#define DOT11_MAXNUMFRAGS 16
|
||||
#define DOT11_MAX_FRAG_LEN 2346
|
||||
|
||||
@ -3140,8 +3138,7 @@ void brcms_c_reset(struct brcms_c_info *wlc)
|
||||
brcms_c_statsupd(wlc);
|
||||
|
||||
/* reset our snapshot of macstat counters */
|
||||
memset((char *)wlc->core->macstat_snapshot, 0,
|
||||
sizeof(struct macstat));
|
||||
memset(wlc->core->macstat_snapshot, 0, sizeof(struct macstat));
|
||||
|
||||
brcms_b_reset(wlc->hw);
|
||||
}
|
||||
@ -4054,7 +4051,7 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
|
||||
return;
|
||||
}
|
||||
|
||||
memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
|
||||
memset(&acp_shm, 0, sizeof(struct shm_acparams));
|
||||
/* fill in shm ac params struct */
|
||||
acp_shm.txop = params->txop;
|
||||
/* convert from units of 32us to us for ucode */
|
||||
@ -4770,7 +4767,7 @@ static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
|
||||
struct brcms_bss_info *bi = wlc->default_bss;
|
||||
|
||||
/* init default and target BSS with some sane initial values */
|
||||
memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
|
||||
memset(bi, 0, sizeof(*bi));
|
||||
bi->beacon_period = BEACON_INTERVAL_DEFAULT;
|
||||
|
||||
/* fill the default channel as the first valid channel
|
||||
@ -5299,7 +5296,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
|
||||
brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
|
||||
|
||||
/* Clear rateset override */
|
||||
memset(&rs, 0, sizeof(struct brcms_c_rateset));
|
||||
memset(&rs, 0, sizeof(rs));
|
||||
|
||||
switch (gmode) {
|
||||
case GMODE_LEGACY_B:
|
||||
@ -5522,7 +5519,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
|
||||
if (rs->count > BRCMS_NUMRATES)
|
||||
return -ENOBUFS;
|
||||
|
||||
memset(&internal_rs, 0, sizeof(struct brcms_c_rateset));
|
||||
memset(&internal_rs, 0, sizeof(internal_rs));
|
||||
|
||||
/* Copy only legacy rateset section */
|
||||
internal_rs.count = rs->count;
|
||||
@ -5548,8 +5545,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
|
||||
|
||||
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
|
||||
{
|
||||
if (period < DOT11_MIN_BEACON_PERIOD ||
|
||||
period > DOT11_MAX_BEACON_PERIOD)
|
||||
if (period == 0)
|
||||
return -EINVAL;
|
||||
|
||||
wlc->default_bss->beacon_period = period;
|
||||
@ -5626,7 +5622,7 @@ int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
|
||||
for (i = 0; i < BRCMS_MAXMODULES; i++) {
|
||||
if (!strcmp(wlc->modulecb[i].name, name) &&
|
||||
(wlc->modulecb[i].hdl == hdl)) {
|
||||
memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
|
||||
memset(&wlc->modulecb[i], 0, sizeof(wlc->modulecb[i]));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -6446,10 +6442,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
|
||||
|
||||
if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
|
||||
&& (!is_mcs_rate(rspec[k]))) {
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"wl%d: %s: IEEE80211_TX_"
|
||||
"RC_MCS != is_mcs_rate(rspec)\n",
|
||||
wlc->pub->unit, __func__);
|
||||
brcms_warn(wlc->hw->d11core,
|
||||
"wl%d: %s: IEEE80211_TX_RC_MCS != is_mcs_rate(rspec)\n",
|
||||
wlc->pub->unit, __func__);
|
||||
}
|
||||
|
||||
if (is_mcs_rate(rspec[k])) {
|
||||
@ -6682,11 +6677,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
|
||||
(struct ofdm_phy_hdr *) rts_plcp) :
|
||||
rts_plcp[0]) << 8;
|
||||
} else {
|
||||
memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
|
||||
memset((char *)&txh->rts_frame, 0,
|
||||
sizeof(struct ieee80211_rts));
|
||||
memset((char *)txh->RTSPLCPFallback, 0,
|
||||
sizeof(txh->RTSPLCPFallback));
|
||||
memset(txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
|
||||
memset(&txh->rts_frame, 0, sizeof(struct ieee80211_rts));
|
||||
memset(txh->RTSPLCPFallback, 0, sizeof(txh->RTSPLCPFallback));
|
||||
txh->RTSDurFallback = 0;
|
||||
}
|
||||
|
||||
@ -6841,21 +6834,19 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
|
||||
wlc->fragthresh[queue] =
|
||||
(u16) newfragthresh;
|
||||
} else {
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"wl%d: %s txop invalid "
|
||||
"for rate %d\n",
|
||||
wlc->pub->unit, fifo_names[queue],
|
||||
rspec2rate(rspec[0]));
|
||||
brcms_warn(wlc->hw->d11core,
|
||||
"wl%d: %s txop invalid for rate %d\n",
|
||||
wlc->pub->unit, fifo_names[queue],
|
||||
rspec2rate(rspec[0]));
|
||||
}
|
||||
|
||||
if (dur > wlc->edcf_txop[ac])
|
||||
brcms_err(wlc->hw->d11core,
|
||||
"wl%d: %s: %s txop "
|
||||
"exceeded phylen %d/%d dur %d/%d\n",
|
||||
wlc->pub->unit, __func__,
|
||||
fifo_names[queue],
|
||||
phylen, wlc->fragthresh[queue],
|
||||
dur, wlc->edcf_txop[ac]);
|
||||
brcms_warn(wlc->hw->d11core,
|
||||
"wl%d: %s: %s txop exceeded phylen %d/%d dur %d/%d\n",
|
||||
wlc->pub->unit, __func__,
|
||||
fifo_names[queue],
|
||||
phylen, wlc->fragthresh[queue],
|
||||
dur, wlc->edcf_txop[ac]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7330,7 +7321,7 @@ brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
|
||||
*len = hdr_len + body_len;
|
||||
|
||||
/* format PHY and MAC headers */
|
||||
memset((char *)buf, 0, hdr_len);
|
||||
memset(buf, 0, hdr_len);
|
||||
|
||||
plcp = (struct cck_phy_hdr *) buf;
|
||||
|
||||
@ -7401,9 +7392,13 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
||||
struct brcms_bss_cfg *cfg,
|
||||
bool suspend)
|
||||
{
|
||||
u16 prb_resp[BCN_TMPL_LEN / 2];
|
||||
u16 *prb_resp;
|
||||
int len = BCN_TMPL_LEN;
|
||||
|
||||
prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
|
||||
if (!prb_resp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* write the probe response to hardware, or save in
|
||||
* the config structure
|
||||
@ -7437,6 +7432,8 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
||||
|
||||
if (suspend)
|
||||
brcms_c_enable_mac(wlc);
|
||||
|
||||
kfree(prb_resp);
|
||||
}
|
||||
|
||||
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
|
||||
|
@ -572,26 +572,11 @@ il3945_tx_skb(struct il_priv *il,
|
||||
il3945_hw_build_tx_cmd_rate(il, out_cmd, info, hdr, sta_id);
|
||||
|
||||
/* Total # bytes to be transmitted */
|
||||
len = (u16) skb->len;
|
||||
tx_cmd->len = cpu_to_le16(len);
|
||||
tx_cmd->len = cpu_to_le16((u16) skb->len);
|
||||
|
||||
il_update_stats(il, true, fc, len);
|
||||
tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
|
||||
tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
|
||||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
} else {
|
||||
wait_write_ptr = 1;
|
||||
txq->need_update = 0;
|
||||
}
|
||||
|
||||
D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
|
||||
D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
|
||||
il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd));
|
||||
il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr,
|
||||
ieee80211_hdrlen(fc));
|
||||
|
||||
/*
|
||||
* Use the first empty entry in this queue's command buffer array
|
||||
* to contain the Tx command and MAC header concatenated together
|
||||
@ -610,14 +595,8 @@ il3945_tx_skb(struct il_priv *il,
|
||||
* within command buffer array. */
|
||||
txcmd_phys =
|
||||
pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE);
|
||||
/* we do not map meta data ... so we can safely access address to
|
||||
* provide to unmap command*/
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, len);
|
||||
|
||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||
* first entry */
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
|
||||
goto drop_unlock;
|
||||
|
||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||
* if any (802.11 null frames have no payload). */
|
||||
@ -626,10 +605,34 @@ il3945_tx_skb(struct il_priv *il,
|
||||
phys_addr =
|
||||
pci_map_single(il->pci_dev, skb->data + hdr_len, len,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||
* first entry */
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0);
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, len);
|
||||
if (len)
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0,
|
||||
U32_PAD(len));
|
||||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
} else {
|
||||
wait_write_ptr = 1;
|
||||
txq->need_update = 0;
|
||||
}
|
||||
|
||||
il_update_stats(il, true, fc, skb->len);
|
||||
|
||||
D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
|
||||
D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
|
||||
il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd));
|
||||
il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr,
|
||||
ieee80211_hdrlen(fc));
|
||||
|
||||
/* Tell device the write idx *just past* this latest filled TFD */
|
||||
q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||
il_txq_update_write_ptr(il, txq);
|
||||
|
@ -1793,8 +1793,7 @@ il4965_tx_skb(struct il_priv *il,
|
||||
memcpy(tx_cmd->hdr, hdr, hdr_len);
|
||||
|
||||
/* Total # bytes to be transmitted */
|
||||
len = (u16) skb->len;
|
||||
tx_cmd->len = cpu_to_le16(len);
|
||||
tx_cmd->len = cpu_to_le16((u16) skb->len);
|
||||
|
||||
if (info->control.hw_key)
|
||||
il4965_tx_cmd_build_hwcrypto(il, info, tx_cmd, skb, sta_id);
|
||||
@ -1804,7 +1803,6 @@ il4965_tx_skb(struct il_priv *il,
|
||||
|
||||
il4965_tx_cmd_build_rate(il, tx_cmd, info, sta, fc);
|
||||
|
||||
il_update_stats(il, true, fc, len);
|
||||
/*
|
||||
* Use the first empty entry in this queue's command buffer array
|
||||
* to contain the Tx command and MAC header concatenated together
|
||||
@ -1826,18 +1824,8 @@ il4965_tx_skb(struct il_priv *il,
|
||||
txcmd_phys =
|
||||
pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, firstlen);
|
||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||
* first entry */
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
|
||||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
} else {
|
||||
wait_write_ptr = 1;
|
||||
txq->need_update = 0;
|
||||
}
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
|
||||
goto drop_unlock;
|
||||
|
||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||
* if any (802.11 null frames have no payload). */
|
||||
@ -1846,8 +1834,24 @@ il4965_tx_skb(struct il_priv *il,
|
||||
phys_addr =
|
||||
pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||
* first entry */
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, firstlen);
|
||||
if (secondlen)
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen,
|
||||
0, 0);
|
||||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
} else {
|
||||
wait_write_ptr = 1;
|
||||
txq->need_update = 0;
|
||||
}
|
||||
|
||||
scratch_phys =
|
||||
@ -1860,6 +1864,8 @@ il4965_tx_skb(struct il_priv *il,
|
||||
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
|
||||
tx_cmd->dram_msb_ptr = il_get_dma_hi_addr(scratch_phys);
|
||||
|
||||
il_update_stats(il, true, fc, skb->len);
|
||||
|
||||
D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
|
||||
D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
|
||||
il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd, sizeof(*tx_cmd));
|
||||
@ -5733,7 +5739,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags =
|
||||
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
if (il->cfg->sku & IL_SKU_N)
|
||||
|
@ -1183,8 +1183,7 @@ il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta,
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
||||
if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) ==
|
||||
WLAN_HT_CAP_SM_PS_STATIC)
|
||||
if (sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
return -1;
|
||||
|
||||
/* Need both Tx chains/antennas to support MIMO */
|
||||
|
@ -1830,32 +1830,30 @@ il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
|
||||
__le32 sta_flags;
|
||||
u8 mimo_ps_mode;
|
||||
|
||||
if (!sta || !sta_ht_inf->ht_supported)
|
||||
goto done;
|
||||
|
||||
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
|
||||
D_ASSOC("spatial multiplexing power save mode: %s\n",
|
||||
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? "static" :
|
||||
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? "dynamic" :
|
||||
(sta->smps_mode == IEEE80211_SMPS_STATIC) ? "static" :
|
||||
(sta->smps_mode == IEEE80211_SMPS_DYNAMIC) ? "dynamic" :
|
||||
"disabled");
|
||||
|
||||
sta_flags = il->stations[idx].sta.station_flags;
|
||||
|
||||
sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
|
||||
|
||||
switch (mimo_ps_mode) {
|
||||
case WLAN_HT_CAP_SM_PS_STATIC:
|
||||
switch (sta->smps_mode) {
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
sta_flags |= STA_FLG_MIMO_DIS_MSK;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DYNAMIC:
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DISABLED:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
break;
|
||||
default:
|
||||
IL_WARN("Invalid MIMO PS mode %d\n", mimo_ps_mode);
|
||||
IL_WARN("Invalid MIMO PS mode %d\n", sta->smps_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3162,18 +3160,23 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
|
||||
idx, il->cmd_queue);
|
||||
}
|
||||
#endif
|
||||
|
||||
phys_addr =
|
||||
pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) {
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
dma_unmap_addr_set(out_meta, mapping, phys_addr);
|
||||
dma_unmap_len_set(out_meta, len, fix_size);
|
||||
|
||||
txq->need_update = 1;
|
||||
|
||||
if (il->ops->txq_update_byte_cnt_tbl)
|
||||
/* Set up entry in queue's byte count circular buffer */
|
||||
il->ops->txq_update_byte_cnt_tbl(il, txq, 0);
|
||||
|
||||
phys_addr =
|
||||
pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
dma_unmap_addr_set(out_meta, mapping, phys_addr);
|
||||
dma_unmap_len_set(out_meta, len, fix_size);
|
||||
|
||||
il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, 1,
|
||||
U32_PAD(cmd->len));
|
||||
|
||||
@ -3181,6 +3184,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
|
||||
q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||
il_txq_update_write_ptr(il, txq);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&il->hcmd_lock, flags);
|
||||
return idx;
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
|
||||
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta_ht_cap *ht_cap);
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
||||
{
|
||||
|
@ -3897,6 +3897,24 @@ struct iwlagn_wowlan_kek_kck_material_cmd {
|
||||
__le64 replay_ctr;
|
||||
} __packed;
|
||||
|
||||
#define RF_KILL_INDICATOR_FOR_WOWLAN 0x87
|
||||
|
||||
/*
|
||||
* REPLY_WOWLAN_GET_STATUS = 0xe5
|
||||
*/
|
||||
struct iwlagn_wowlan_status {
|
||||
__le64 replay_ctr;
|
||||
__le32 rekey_status;
|
||||
__le32 wakeup_reason;
|
||||
u8 pattern_number;
|
||||
u8 reserved1;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le16 non_qos_seq_ctr;
|
||||
__le16 reserved2;
|
||||
union iwlagn_all_tsc_rsc tsc_rsc;
|
||||
__le16 reserved3;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
|
||||
*/
|
||||
|
@ -145,14 +145,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
|
||||
IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_QUEUE_CONTROL |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_WANT_MONITOR_VIF |
|
||||
IEEE80211_HW_SCAN_WHILE_IDLE;
|
||||
IEEE80211_HW_WANT_MONITOR_VIF;
|
||||
|
||||
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
|
||||
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT;
|
||||
@ -442,53 +441,155 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct iwl_resume_data {
|
||||
struct iwl_priv *priv;
|
||||
struct iwlagn_wowlan_status *cmd;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
static bool iwl_resume_status_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwl_resume_data *resume_data = data;
|
||||
struct iwl_priv *priv = resume_data->priv;
|
||||
u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
|
||||
if (len - 4 != sizeof(*resume_data->cmd)) {
|
||||
IWL_ERR(priv, "rx wrong size data\n");
|
||||
return true;
|
||||
}
|
||||
memcpy(resume_data->cmd, pkt->data, sizeof(*resume_data->cmd));
|
||||
resume_data->valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct ieee80211_vif *vif;
|
||||
unsigned long flags;
|
||||
u32 base, status = 0xffffffff;
|
||||
int ret = -EIO;
|
||||
u32 base;
|
||||
int ret;
|
||||
enum iwl_d3_status d3_status;
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
u32 error_id;
|
||||
} err_info;
|
||||
struct iwl_notification_wait status_wait;
|
||||
static const u8 status_cmd[] = {
|
||||
REPLY_WOWLAN_GET_STATUS,
|
||||
};
|
||||
struct iwlagn_wowlan_status status_data = {};
|
||||
struct iwl_resume_data resume_data = {
|
||||
.priv = priv,
|
||||
.cmd = &status_data,
|
||||
.valid = false,
|
||||
};
|
||||
struct cfg80211_wowlan_wakeup wakeup = {
|
||||
.pattern_idx = -1,
|
||||
};
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
const struct fw_img *img;
|
||||
#endif
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
if (iwl_trans_grab_nic_access(priv->trans, true, &flags)) {
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base);
|
||||
status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_trans_release_nic_access(priv->trans, &flags);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (ret == 0) {
|
||||
const struct fw_img *img;
|
||||
|
||||
img = &(priv->fw->img[IWL_UCODE_WOWLAN]);
|
||||
if (!priv->wowlan_sram) {
|
||||
priv->wowlan_sram =
|
||||
kzalloc(img->sec[IWL_UCODE_SECTION_DATA].len,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
if (priv->wowlan_sram)
|
||||
iwl_trans_read_mem(
|
||||
priv->trans, 0x800000,
|
||||
priv->wowlan_sram,
|
||||
img->sec[IWL_UCODE_SECTION_DATA].len / 4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* we'll clear ctx->vif during iwlagn_prepare_restart() */
|
||||
vif = ctx->vif;
|
||||
|
||||
ret = iwl_trans_d3_resume(priv->trans, &d3_status);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
if (d3_status != IWL_D3_STATUS_ALIVE) {
|
||||
IWL_INFO(priv, "Device was reset during suspend\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
IWL_WARN(priv, "Invalid error table during resume!\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iwl_trans_read_mem_bytes(priv->trans, base,
|
||||
&err_info, sizeof(err_info));
|
||||
|
||||
if (err_info.valid) {
|
||||
IWL_INFO(priv, "error table is valid (%d, 0x%x)\n",
|
||||
err_info.valid, err_info.error_id);
|
||||
if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
|
||||
wakeup.rfkill_release = true;
|
||||
ieee80211_report_wowlan_wakeup(vif, &wakeup,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
img = &priv->fw->img[IWL_UCODE_WOWLAN];
|
||||
if (!priv->wowlan_sram)
|
||||
priv->wowlan_sram =
|
||||
kzalloc(img->sec[IWL_UCODE_SECTION_DATA].len,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (priv->wowlan_sram)
|
||||
iwl_trans_read_mem(priv->trans, 0x800000,
|
||||
priv->wowlan_sram,
|
||||
img->sec[IWL_UCODE_SECTION_DATA].len / 4);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is very strange. The GET_STATUS command is sent but the device
|
||||
* doesn't reply properly, it seems it doesn't close the RBD so one is
|
||||
* always left open ... As a result, we need to send another command
|
||||
* and have to reset the driver afterwards. As we need to switch to
|
||||
* runtime firmware again that'll happen.
|
||||
*/
|
||||
|
||||
iwl_init_notification_wait(&priv->notif_wait, &status_wait, status_cmd,
|
||||
ARRAY_SIZE(status_cmd), iwl_resume_status_fn,
|
||||
&resume_data);
|
||||
|
||||
iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_GET_STATUS, CMD_ASYNC, 0, NULL);
|
||||
iwl_dvm_send_cmd_pdu(priv, REPLY_ECHO, CMD_ASYNC, 0, NULL);
|
||||
/* an RBD is left open in the firmware now! */
|
||||
|
||||
ret = iwl_wait_notification(&priv->notif_wait, &status_wait, HZ/5);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
if (resume_data.valid && priv->contexts[IWL_RXON_CTX_BSS].vif) {
|
||||
u32 reasons = le32_to_cpu(status_data.wakeup_reason);
|
||||
struct cfg80211_wowlan_wakeup *wakeup_report;
|
||||
|
||||
IWL_INFO(priv, "WoWLAN wakeup reason(s): 0x%.8x\n", reasons);
|
||||
|
||||
if (reasons) {
|
||||
if (reasons & IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET)
|
||||
wakeup.magic_pkt = true;
|
||||
if (reasons & IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH)
|
||||
wakeup.pattern_idx = status_data.pattern_number;
|
||||
if (reasons & (IWLAGN_WOWLAN_WAKEUP_BEACON_MISS |
|
||||
IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE))
|
||||
wakeup.disconnect = true;
|
||||
if (reasons & IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL)
|
||||
wakeup.gtk_rekey_failure = true;
|
||||
if (reasons & IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ)
|
||||
wakeup.eap_identity_req = true;
|
||||
if (reasons & IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE)
|
||||
wakeup.four_way_handshake = true;
|
||||
wakeup_report = &wakeup;
|
||||
} else {
|
||||
wakeup_report = NULL;
|
||||
}
|
||||
|
||||
ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
|
||||
}
|
||||
|
||||
priv->wowlan = false;
|
||||
|
||||
iwlagn_prepare_restart(priv);
|
||||
@ -497,6 +598,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
iwl_connection_init_rx_config(priv, ctx);
|
||||
iwlagn_set_rxon_chain(priv, ctx);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
|
@ -1289,8 +1289,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
||||
if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
|
||||
== WLAN_HT_CAP_SM_PS_STATIC)
|
||||
if (sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
return -1;
|
||||
|
||||
/* Need both Tx chains/antennas to support MIMO */
|
||||
@ -1305,7 +1304,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
|
||||
tbl->max_search = IWL_MAX_SEARCH;
|
||||
rate_mask = lq_sta->active_mimo2_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
@ -1345,8 +1344,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
||||
if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
|
||||
== WLAN_HT_CAP_SM_PS_STATIC)
|
||||
if (sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
return -1;
|
||||
|
||||
/* Need both Tx chains/antennas to support MIMO */
|
||||
@ -1361,7 +1359,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
|
||||
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
|
||||
rate_mask = lq_sta->active_mimo3_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
@ -1410,7 +1408,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
|
||||
tbl->max_search = IWL_MAX_SEARCH;
|
||||
rate_mask = lq_sta->active_siso_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
@ -790,7 +790,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
|
||||
|
||||
ieee80211_rx(priv->hw, skb);
|
||||
ieee80211_rx_ni(priv->hw, skb);
|
||||
}
|
||||
|
||||
static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
|
||||
|
@ -1545,10 +1545,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
bss_conf->bssid);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC &&
|
||||
priv->beacon_ctx) {
|
||||
if (changes & BSS_CHANGED_BEACON && priv->beacon_ctx == ctx) {
|
||||
if (iwlagn_update_beacon(priv, vif))
|
||||
IWL_ERR(priv, "Error sending IBSS beacon\n");
|
||||
IWL_ERR(priv, "Error updating beacon\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -77,7 +77,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
|
||||
sta_id);
|
||||
|
||||
spin_lock(&priv->sta_lock);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
switch (add_sta_resp->status) {
|
||||
case ADD_STA_SUCCESS_MSK:
|
||||
@ -119,7 +119,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
priv->stations[sta_id].sta.mode ==
|
||||
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
|
||||
addsta->sta.addr);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -173,7 +173,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
|
||||
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta_ht_cap *ht_cap)
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
|
||||
return false;
|
||||
@ -183,20 +183,11 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Remainder of this function checks ht_cap, but if it's
|
||||
* NULL then we can do HT40 (special case for RXON)
|
||||
*/
|
||||
if (!ht_cap)
|
||||
/* special case for RXON */
|
||||
if (!sta)
|
||||
return true;
|
||||
|
||||
if (!ht_cap->ht_supported)
|
||||
return false;
|
||||
|
||||
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
}
|
||||
|
||||
static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
|
||||
@ -205,7 +196,6 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
|
||||
__le32 *flags, __le32 *mask)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
|
||||
u8 mimo_ps_mode;
|
||||
|
||||
*mask = STA_FLG_RTS_MIMO_PROT_MSK |
|
||||
STA_FLG_MIMO_DIS_MSK |
|
||||
@ -217,26 +207,24 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
|
||||
if (!sta || !sta_ht_inf->ht_supported)
|
||||
return;
|
||||
|
||||
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n",
|
||||
sta->addr,
|
||||
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
|
||||
(sta->smps_mode == IEEE80211_SMPS_STATIC) ?
|
||||
"static" :
|
||||
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
|
||||
(sta->smps_mode == IEEE80211_SMPS_DYNAMIC) ?
|
||||
"dynamic" : "disabled");
|
||||
|
||||
switch (mimo_ps_mode) {
|
||||
case WLAN_HT_CAP_SM_PS_STATIC:
|
||||
switch (sta->smps_mode) {
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
*flags |= STA_FLG_MIMO_DIS_MSK;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DYNAMIC:
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
*flags |= STA_FLG_RTS_MIMO_PROT_MSK;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DISABLED:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
break;
|
||||
default:
|
||||
IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
|
||||
IWL_WARN(priv, "Invalid MIMO PS mode %d\n", sta->smps_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -246,7 +234,7 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
|
||||
*flags |= cpu_to_le32(
|
||||
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, sta))
|
||||
*flags |= STA_FLG_HT40_EN_MSK;
|
||||
}
|
||||
|
||||
|
@ -1117,7 +1117,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
|
||||
IWLAGN_TX_RES_RA_POS;
|
||||
|
||||
spin_lock(&priv->sta_lock);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
if (is_agg)
|
||||
iwl_rx_reply_tx_agg(priv, tx_resp);
|
||||
@ -1207,7 +1207,15 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
freed++;
|
||||
}
|
||||
|
||||
WARN_ON(!is_agg && freed != 1);
|
||||
if (tid != IWL_TID_NON_QOS) {
|
||||
priv->tid_data[sta_id][tid].next_reclaimed =
|
||||
next_reclaimed;
|
||||
IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
|
||||
next_reclaimed);
|
||||
}
|
||||
|
||||
if (!is_agg && freed != 1)
|
||||
IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed);
|
||||
|
||||
/*
|
||||
* An offchannel frame can be send only on the AUX queue, where
|
||||
@ -1228,11 +1236,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
le16_to_cpu(tx_resp->seq_ctl));
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
while (!skb_queue_empty(&skbs)) {
|
||||
skb = __skb_dequeue(&skbs);
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
ieee80211_tx_status_ni(priv->hw, skb);
|
||||
}
|
||||
|
||||
if (is_offchannel_skb)
|
||||
@ -1279,12 +1287,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
tid = ba_resp->tid;
|
||||
agg = &priv->tid_data[sta_id][tid].agg;
|
||||
|
||||
spin_lock(&priv->sta_lock);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
if (unlikely(!agg->wait_for_ba)) {
|
||||
if (unlikely(ba_resp->bitmap))
|
||||
IWL_ERR(priv, "Received BA when not expected\n");
|
||||
spin_unlock(&priv->sta_lock);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1298,7 +1306,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
IWL_DEBUG_TX_QUEUES(priv,
|
||||
"Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n",
|
||||
scd_flow, sta_id, tid, agg->txq_id);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1367,11 +1375,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&priv->sta_lock);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||
skb = __skb_dequeue(&reclaimed_skbs);
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
ieee80211_tx_status_ni(priv->hw, skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -113,13 +113,13 @@ struct iwl_cfg;
|
||||
* May sleep
|
||||
* @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
|
||||
* HCMD the this Rx responds to.
|
||||
* Must be atomic and called with BH disabled.
|
||||
* This callback may sleep, it is called from a threaded IRQ handler.
|
||||
* @queue_full: notifies that a HW queue is full.
|
||||
* Must be atomic and called with BH disabled.
|
||||
* @queue_not_full: notifies that a HW queue is not full any more.
|
||||
* Must be atomic and called with BH disabled.
|
||||
* @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
|
||||
* the radio is killed. Must be atomic.
|
||||
* the radio is killed. May sleep.
|
||||
* @free_skb: allows the transport layer to free skbs that haven't been
|
||||
* reclaimed by the op_mode. This can happen when the driver is freed and
|
||||
* there are Tx packets pending in the transport layer.
|
||||
@ -130,8 +130,7 @@ struct iwl_cfg;
|
||||
* called with BH disabled.
|
||||
* @nic_config: configure NIC, called before firmware is started.
|
||||
* May sleep
|
||||
* @wimax_active: invoked when WiMax becomes active. Must be atomic and called
|
||||
* with BH disabled.
|
||||
* @wimax_active: invoked when WiMax becomes active. May sleep
|
||||
*/
|
||||
struct iwl_op_mode_ops {
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
|
||||
@ -178,6 +177,7 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
might_sleep();
|
||||
return op_mode->ops->rx(op_mode, rxb, cmd);
|
||||
}
|
||||
|
||||
@ -196,6 +196,7 @@ static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
|
||||
static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode,
|
||||
bool state)
|
||||
{
|
||||
might_sleep();
|
||||
op_mode->ops->hw_rf_kill(op_mode, state);
|
||||
}
|
||||
|
||||
@ -223,6 +224,7 @@ static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
|
||||
|
||||
static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
might_sleep();
|
||||
op_mode->ops->wimax_active(op_mode);
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/mm.h> /* for page_address */
|
||||
#include <linux/lockdep.h>
|
||||
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-config.h"
|
||||
@ -526,6 +527,10 @@ struct iwl_trans {
|
||||
|
||||
struct dentry *dbgfs_dir;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
struct lockdep_map sync_cmd_lockdep_map;
|
||||
#endif
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
char trans_specific[0] __aligned(sizeof(void *));
|
||||
@ -602,12 +607,22 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||
struct iwl_host_cmd *cmd)
|
||||
struct iwl_host_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
|
||||
"%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->send_cmd(trans, cmd);
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
|
||||
|
||||
ret = trans->ops->send_cmd(trans, cmd);
|
||||
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_release(&trans->sync_cmd_lockdep_map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline struct iwl_device_cmd *
|
||||
@ -791,4 +806,14 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
|
||||
int __must_check iwl_pci_register_driver(void);
|
||||
void iwl_pci_unregister_driver(void);
|
||||
|
||||
static inline void trans_lockdep_init(struct iwl_trans *trans)
|
||||
{
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
static struct lock_class_key __key;
|
||||
|
||||
lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map",
|
||||
&__key, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __iwl_trans_h__ */
|
||||
|
@ -97,14 +97,14 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
struct inet6_ifaddr *ifa;
|
||||
int idx = 0;
|
||||
|
||||
read_lock(&idev->lock);
|
||||
read_lock_bh(&idev->lock);
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
mvmvif->target_ipv6_addrs[idx] = ifa->addr;
|
||||
idx++;
|
||||
if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS)
|
||||
break;
|
||||
}
|
||||
read_unlock(&idev->lock);
|
||||
read_unlock_bh(&idev->lock);
|
||||
|
||||
mvmvif->num_target_ipv6_addrs = idx;
|
||||
}
|
||||
@ -490,7 +490,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_sta_add_to_fw(mvm, ap_sta);
|
||||
ret = iwl_mvm_sta_send_to_fw(mvm, ap_sta, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta);
|
||||
@ -763,6 +763,146 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u32 base = mvm->error_event_table;
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
u32 error_id;
|
||||
} err_info;
|
||||
struct cfg80211_wowlan_wakeup wakeup = {
|
||||
.pattern_idx = -1,
|
||||
};
|
||||
struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WOWLAN_GET_STATUSES,
|
||||
.flags = CMD_SYNC | CMD_WANT_SKB,
|
||||
};
|
||||
struct iwl_wowlan_status *status;
|
||||
u32 reasons;
|
||||
int ret, len;
|
||||
bool pkt8023 = false;
|
||||
struct sk_buff *pkt = NULL;
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, base,
|
||||
&err_info, sizeof(err_info));
|
||||
|
||||
if (err_info.valid) {
|
||||
IWL_INFO(mvm, "error table is valid (%d)\n",
|
||||
err_info.valid);
|
||||
if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
|
||||
wakeup.rfkill_release = true;
|
||||
ieee80211_report_wowlan_wakeup(vif, &wakeup,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* only for tracing for now */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret);
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to query status (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* RF-kill already asserted again... */
|
||||
if (!cmd.resp_pkt)
|
||||
return;
|
||||
|
||||
len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) {
|
||||
IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = (void *)cmd.resp_pkt->data;
|
||||
|
||||
if (len - sizeof(struct iwl_cmd_header) !=
|
||||
sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) {
|
||||
IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
reasons = le32_to_cpu(status->wakeup_reasons);
|
||||
|
||||
if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) {
|
||||
wakeup_report = NULL;
|
||||
goto report;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) {
|
||||
wakeup.magic_pkt = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) {
|
||||
wakeup.pattern_idx =
|
||||
le16_to_cpu(status->pattern_number);
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
|
||||
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH))
|
||||
wakeup.disconnect = true;
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) {
|
||||
wakeup.gtk_rekey_failure = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) {
|
||||
wakeup.rfkill_release = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) {
|
||||
wakeup.eap_identity_req = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) {
|
||||
wakeup.four_way_handshake = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (status->wake_packet_bufsize) {
|
||||
u32 pktsize = le32_to_cpu(status->wake_packet_bufsize);
|
||||
u32 pktlen = le32_to_cpu(status->wake_packet_length);
|
||||
|
||||
if (pkt8023) {
|
||||
pkt = alloc_skb(pktsize, GFP_KERNEL);
|
||||
if (!pkt)
|
||||
goto report;
|
||||
memcpy(skb_put(pkt, pktsize), status->wake_packet,
|
||||
pktsize);
|
||||
if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
|
||||
goto report;
|
||||
wakeup.packet = pkt->data;
|
||||
wakeup.packet_present_len = pkt->len;
|
||||
wakeup.packet_len = pkt->len - (pktlen - pktsize);
|
||||
wakeup.packet_80211 = false;
|
||||
} else {
|
||||
wakeup.packet = status->wake_packet;
|
||||
wakeup.packet_present_len = pktsize;
|
||||
wakeup.packet_len = pktlen;
|
||||
wakeup.packet_80211 = true;
|
||||
}
|
||||
}
|
||||
|
||||
report:
|
||||
ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
|
||||
kfree_skb(pkt);
|
||||
|
||||
out:
|
||||
iwl_free_resp(&cmd);
|
||||
}
|
||||
|
||||
int iwl_mvm_resume(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
@ -770,14 +910,8 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
|
||||
.mvm = mvm,
|
||||
};
|
||||
struct ieee80211_vif *vif = NULL;
|
||||
u32 base;
|
||||
int ret;
|
||||
enum iwl_d3_status d3_status;
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
u32 error_id;
|
||||
} err_info;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
@ -800,27 +934,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
base = mvm->error_event_table;
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, base,
|
||||
&err_info, sizeof(err_info));
|
||||
|
||||
if (err_info.valid) {
|
||||
IWL_INFO(mvm, "error table is valid (%d)\n",
|
||||
err_info.valid);
|
||||
if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN)
|
||||
IWL_ERR(mvm, "this was due to RF-kill\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* TODO: get status and whatever else ... */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_GET_STATUSES, CMD_SYNC, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to query status (%d)\n", ret);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to query offloads (%d)\n", ret);
|
||||
iwl_mvm_query_wakeup_reasons(mvm, vif);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
@ -633,6 +633,9 @@ struct iwl_binding_cmd {
|
||||
__le32 phy;
|
||||
} __packed; /* BINDING_CMD_API_S_VER_1 */
|
||||
|
||||
/* The maximal number of fragments in the FW's schedule session */
|
||||
#define IWL_MVM_MAX_QUOTA 128
|
||||
|
||||
/**
|
||||
* struct iwl_time_quota_data - configuration of time quota per binding
|
||||
* @id_and_color: ID and color of the relevant Binding
|
||||
|
@ -621,10 +621,6 @@ int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
|
||||
(flags & CT_KILL_CARD_DISABLED) ?
|
||||
"Reached" : "Not reached");
|
||||
|
||||
if (flags & CARD_DISABLED_MSK)
|
||||
iwl_write32(mvm->trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -584,7 +584,11 @@ static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_data_sta *ctxt_sta)
|
||||
{
|
||||
ctxt_sta->is_assoc = cpu_to_le32(vif->bss_conf.assoc ? 1 : 0);
|
||||
/* We need the dtim_period to set the MAC as associated */
|
||||
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period)
|
||||
ctxt_sta->is_assoc = cpu_to_le32(1);
|
||||
else
|
||||
ctxt_sta->is_assoc = cpu_to_le32(0);
|
||||
|
||||
ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
|
||||
ctxt_sta->bi_reciprocal =
|
||||
|
@ -113,8 +113,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_QUEUE_CONTROL |
|
||||
IEEE80211_HW_WANT_MONITOR_VIF |
|
||||
IEEE80211_HW_SCAN_WHILE_IDLE |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION;
|
||||
@ -475,7 +474,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
||||
if (mvm->vif_count > 1) {
|
||||
IWL_DEBUG_MAC80211(mvm,
|
||||
"Disable power on existing interfaces\n");
|
||||
ieee80211_iterate_active_interfaces(
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_pm_disable_iterator, mvm);
|
||||
@ -671,8 +670,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
IWL_ERR(mvm, "failed to update quotas\n");
|
||||
return;
|
||||
}
|
||||
iwl_mvm_remove_time_event(mvm, mvmvif,
|
||||
&mvmvif->time_event_data);
|
||||
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
|
||||
/* remove AP station now that the MAC is unassoc */
|
||||
ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
|
||||
@ -684,6 +681,13 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update quotas\n");
|
||||
}
|
||||
} else if (changes & BSS_CHANGED_DTIM_PERIOD) {
|
||||
/*
|
||||
* We received a beacon _after_ association so
|
||||
* remove the session protection.
|
||||
*/
|
||||
iwl_mvm_remove_time_event(mvm, mvmvif,
|
||||
&mvmvif->time_event_data);
|
||||
} else if (changes & BSS_CHANGED_PS) {
|
||||
/*
|
||||
* TODO: remove this temporary code.
|
||||
@ -922,8 +926,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band);
|
||||
ret = 0;
|
||||
ret = iwl_mvm_update_sta(mvm, vif, sta);
|
||||
if (ret == 0)
|
||||
iwl_mvm_rs_rate_init(mvm, sta,
|
||||
mvmvif->phy_ctxt->channel->band);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
ret = 0;
|
||||
|
@ -536,25 +536,28 @@ static int iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode,
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(iwl_mvm_rx_handlers); i++) {
|
||||
const struct iwl_rx_handlers *rx_h = &iwl_mvm_rx_handlers[i];
|
||||
if (rx_h->cmd_id == pkt->hdr.cmd) {
|
||||
struct iwl_async_handler_entry *entry;
|
||||
if (!rx_h->async)
|
||||
return rx_h->fn(mvm, rxb, cmd);
|
||||
struct iwl_async_handler_entry *entry;
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
/* we can't do much... */
|
||||
if (!entry)
|
||||
return 0;
|
||||
if (rx_h->cmd_id != pkt->hdr.cmd)
|
||||
continue;
|
||||
|
||||
entry->rxb._page = rxb_steal_page(rxb);
|
||||
entry->rxb._offset = rxb->_offset;
|
||||
entry->rxb._rx_page_order = rxb->_rx_page_order;
|
||||
entry->fn = rx_h->fn;
|
||||
spin_lock(&mvm->async_handlers_lock);
|
||||
list_add_tail(&entry->list, &mvm->async_handlers_list);
|
||||
spin_unlock(&mvm->async_handlers_lock);
|
||||
schedule_work(&mvm->async_handlers_wk);
|
||||
}
|
||||
if (!rx_h->async)
|
||||
return rx_h->fn(mvm, rxb, cmd);
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
/* we can't do much... */
|
||||
if (!entry)
|
||||
return 0;
|
||||
|
||||
entry->rxb._page = rxb_steal_page(rxb);
|
||||
entry->rxb._offset = rxb->_offset;
|
||||
entry->rxb._rx_page_order = rxb->_rx_page_order;
|
||||
entry->fn = rx_h->fn;
|
||||
spin_lock(&mvm->async_handlers_lock);
|
||||
list_add_tail(&entry->list, &mvm->async_handlers_list);
|
||||
spin_unlock(&mvm->async_handlers_lock);
|
||||
schedule_work(&mvm->async_handlers_wk);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -194,7 +194,7 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
cmd.id_and_color, iwlmvm_mod_params.power_scheme,
|
||||
le16_to_cpu(cmd.flags));
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
|
||||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
|
||||
int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
|
||||
{
|
||||
struct iwl_time_quota_cmd cmd;
|
||||
int i, idx, ret;
|
||||
int i, idx, ret, num_active_bindings, quota, quota_rem;
|
||||
struct iwl_mvm_quota_iterator_data data = {
|
||||
.n_interfaces = {},
|
||||
.colors = { -1, -1, -1, -1 },
|
||||
@ -156,20 +156,39 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
|
||||
iwl_mvm_quota_iterator(&data, newvif->addr, newvif);
|
||||
}
|
||||
|
||||
/*
|
||||
* The FW's scheduling session consists of
|
||||
* IWL_MVM_MAX_QUOTA fragments. Divide these fragments
|
||||
* equally between all the bindings that require quota
|
||||
*/
|
||||
num_active_bindings = 0;
|
||||
for (i = 0; i < MAX_BINDINGS; i++) {
|
||||
cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
|
||||
if (data.n_interfaces[i] > 0)
|
||||
num_active_bindings++;
|
||||
}
|
||||
|
||||
if (!num_active_bindings)
|
||||
goto send_cmd;
|
||||
|
||||
quota = IWL_MVM_MAX_QUOTA / num_active_bindings;
|
||||
quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings;
|
||||
|
||||
for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
|
||||
if (data.n_interfaces[i] <= 0)
|
||||
continue;
|
||||
|
||||
cmd.quotas[idx].id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i]));
|
||||
cmd.quotas[idx].quota = cpu_to_le32(100);
|
||||
cmd.quotas[idx].max_duration = cpu_to_le32(1000);
|
||||
cmd.quotas[idx].quota = cpu_to_le32(quota);
|
||||
cmd.quotas[idx].max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA);
|
||||
idx++;
|
||||
}
|
||||
|
||||
for (i = idx; i < MAX_BINDINGS; i++)
|
||||
cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
|
||||
/* Give the remainder of the session to the first binding */
|
||||
le32_add_cpu(&cmd.quotas[0].quota, quota_rem);
|
||||
|
||||
send_cmd:
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
|
@ -1209,23 +1209,9 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
|
||||
return new_rate;
|
||||
}
|
||||
|
||||
static bool iwl_is_ht40_tx_allowed(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta_ht_cap *ht_cap)
|
||||
static bool iwl_is_ht40_tx_allowed(struct ieee80211_sta *sta)
|
||||
{
|
||||
/*
|
||||
* Remainder of this function checks ht_cap, but if it's
|
||||
* NULL then we can do HT40 (special case for RXON)
|
||||
*/
|
||||
if (!ht_cap)
|
||||
return true;
|
||||
|
||||
if (!ht_cap->ht_supported)
|
||||
return false;
|
||||
|
||||
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1243,8 +1229,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
||||
if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
|
||||
== WLAN_HT_CAP_SM_PS_STATIC)
|
||||
if (sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
return -1;
|
||||
|
||||
/* Need both Tx chains/antennas to support MIMO */
|
||||
@ -1258,7 +1243,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
|
||||
tbl->max_search = IWL_MAX_SEARCH;
|
||||
rate_mask = lq_sta->active_mimo2_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(mvm, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(sta))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
@ -1296,8 +1281,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
||||
if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
|
||||
== WLAN_HT_CAP_SM_PS_STATIC)
|
||||
if (sta->smps_mode == IEEE80211_SMPS_STATIC)
|
||||
return -1;
|
||||
|
||||
/* Need both Tx chains/antennas to support MIMO */
|
||||
@ -1311,7 +1295,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
|
||||
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
|
||||
rate_mask = lq_sta->active_mimo3_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(mvm, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(sta))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
@ -1356,7 +1340,7 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm,
|
||||
tbl->max_search = IWL_MAX_SEARCH;
|
||||
rate_mask = lq_sta->active_siso_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(mvm, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(sta))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
@ -121,7 +121,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
|
||||
|
||||
ieee80211_rx(mvm->hw, skb);
|
||||
ieee80211_rx_ni(mvm->hw, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -81,8 +81,9 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)
|
||||
return IWL_MVM_STATION_COUNT;
|
||||
}
|
||||
|
||||
/* add a NEW station to fw */
|
||||
int iwl_mvm_sta_add_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta)
|
||||
/* send station add/update command to firmware */
|
||||
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
bool update)
|
||||
{
|
||||
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
|
||||
struct iwl_mvm_add_sta_cmd add_sta_cmd;
|
||||
@ -94,8 +95,11 @@ int iwl_mvm_sta_add_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta)
|
||||
|
||||
add_sta_cmd.sta_id = mvm_sta->sta_id;
|
||||
add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
|
||||
add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
|
||||
memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
|
||||
if (!update) {
|
||||
add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
|
||||
memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
|
||||
}
|
||||
add_sta_cmd.add_modify = update ? 1 : 0;
|
||||
|
||||
/* STA_FLG_FAT_EN_MSK ? */
|
||||
/* STA_FLG_MIMO_EN_MSK ? */
|
||||
@ -181,7 +185,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
/* for HW restart - need to reset the seq_number etc... */
|
||||
memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data));
|
||||
|
||||
ret = iwl_mvm_sta_add_to_fw(mvm, sta);
|
||||
ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -195,6 +199,13 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
return iwl_mvm_sta_send_to_fw(mvm, sta, true);
|
||||
}
|
||||
|
||||
int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
bool drain)
|
||||
{
|
||||
@ -1116,7 +1127,8 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
||||
if (WARN_ON_ONCE(mvm_sta->vif != vif))
|
||||
return -EINVAL;
|
||||
|
||||
key_flags = cpu_to_le16(keyconf->keyidx & STA_KEY_FLG_KEYID_MSK);
|
||||
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
||||
STA_KEY_FLG_KEYID_MSK);
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
|
||||
key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
|
||||
|
||||
@ -1154,14 +1166,26 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta, u32 iv32,
|
||||
u16 *phase1key)
|
||||
{
|
||||
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
|
||||
struct iwl_mvm_sta *mvm_sta;
|
||||
u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (!sta) {
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
|
||||
if (WARN_ON(IS_ERR_OR_NULL(sta))) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mvm_sta = (void *)sta->drv_priv;
|
||||
iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
|
||||
iv32, phase1key, CMD_ASYNC);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, int sta_id)
|
||||
|
@ -309,10 +309,14 @@ struct iwl_mvm_int_sta {
|
||||
u32 tfd_queue_msk;
|
||||
};
|
||||
|
||||
int iwl_mvm_sta_add_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta);
|
||||
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
bool update);
|
||||
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
|
@ -76,6 +76,15 @@
|
||||
#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
|
||||
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
|
||||
|
||||
/* For ROC use a TE type which has priority high enough to be scheduled when
|
||||
* there is a concurrent BSS or GO/AP. Currently, use a TE type that has
|
||||
* priority similar to the TE priority used for action scans by the FW.
|
||||
* TODO: This needs to be changed, based on the reason for the ROC, i.e., use
|
||||
* TE_P2P_DEVICE_DISCOVERABLE for remain on channel without mgmt skb, and use
|
||||
* TE_P2P_DEVICE_ACTION_SCAN
|
||||
*/
|
||||
#define IWL_MVM_ROC_TE_TYPE TE_P2P_DEVICE_ACTION_SCAN
|
||||
|
||||
void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_time_event_data *te_data)
|
||||
{
|
||||
@ -175,9 +184,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
|
||||
*/
|
||||
if (te_data->vif->type == NL80211_IFTYPE_STATION &&
|
||||
(!te_data->vif->bss_conf.assoc ||
|
||||
!te_data->vif->bss_conf.dtim_period))
|
||||
!te_data->vif->bss_conf.dtim_period)) {
|
||||
IWL_ERR(mvm,
|
||||
"No assocation and the time event is over already...\n");
|
||||
ieee80211_connection_loss(te_data->vif);
|
||||
}
|
||||
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
} else if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_START) {
|
||||
@ -219,57 +230,86 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool iwl_mvm_time_event_notif(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(notif_wait, struct iwl_mvm, notif_wait);
|
||||
struct iwl_mvm_time_event_data *te_data = data;
|
||||
struct ieee80211_vif *vif = te_data->vif;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_time_event_notif *notif;
|
||||
struct iwl_time_event_resp *resp;
|
||||
int resp_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
|
||||
u32 mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
|
||||
|
||||
/* until we do something else */
|
||||
WARN_ON(te_data->id != TE_BSS_STA_AGGRESSIVE_ASSOC);
|
||||
|
||||
switch (pkt->hdr.cmd) {
|
||||
case TIME_EVENT_CMD:
|
||||
resp = (void *)pkt->data;
|
||||
/* TODO: I can't check that since the fw is buggy - it doesn't
|
||||
* put the right values when we remove a TE. We can be here
|
||||
* when we remove a TE because the remove TE command is sent in
|
||||
* ASYNC...
|
||||
* WARN_ON(mac_id_n_color != le32_to_cpu(resp->id_and_color));
|
||||
*/
|
||||
te_data->uid = le32_to_cpu(resp->unique_id);
|
||||
IWL_DEBUG_TE(mvm, "Got response - UID = 0x%x\n", te_data->uid);
|
||||
return false;
|
||||
|
||||
case TIME_EVENT_NOTIFICATION:
|
||||
notif = (void *)pkt->data;
|
||||
WARN_ON(le32_to_cpu(notif->status) != 1);
|
||||
WARN_ON(mac_id_n_color != le32_to_cpu(notif->id_and_color));
|
||||
/* check if this is our Time Event that is starting */
|
||||
if (le32_to_cpu(notif->unique_id) != te_data->uid)
|
||||
return false;
|
||||
IWL_DEBUG_TE(mvm, "Event %d is starting - time is %d\n",
|
||||
te_data->uid, le32_to_cpu(notif->timestamp));
|
||||
|
||||
WARN_ONCE(!le32_to_cpu(notif->status),
|
||||
"Failed to schedule protected session TE\n");
|
||||
|
||||
te_data->running = true;
|
||||
te_data->end_jiffies = jiffies +
|
||||
TU_TO_JIFFIES(te_data->duration);
|
||||
if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_CMD))
|
||||
return true;
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return false;
|
||||
};
|
||||
if (WARN_ON_ONCE(resp_len != sizeof(pkt->hdr) + sizeof(*resp))) {
|
||||
IWL_ERR(mvm, "Invalid TIME_EVENT_CMD response\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
resp = (void *)pkt->data;
|
||||
te_data->uid = le32_to_cpu(resp->unique_id);
|
||||
IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
|
||||
te_data->uid);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_time_event_data *te_data,
|
||||
struct iwl_time_event_cmd *te_cmd)
|
||||
{
|
||||
static const u8 time_event_response[] = { TIME_EVENT_CMD };
|
||||
struct iwl_notification_wait wait_time_event;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
if (WARN_ON(te_data->id != TE_MAX)) {
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
return -EIO;
|
||||
}
|
||||
te_data->vif = vif;
|
||||
te_data->duration = le32_to_cpu(te_cmd->duration);
|
||||
te_data->id = le32_to_cpu(te_cmd->id);
|
||||
list_add_tail(&te_data->list, &mvm->time_event_list);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
||||
/*
|
||||
* Use a notification wait, which really just processes the
|
||||
* command response and doesn't wait for anything, in order
|
||||
* to be able to process the response and get the UID inside
|
||||
* the RX path. Using CMD_WANT_SKB doesn't work because it
|
||||
* stores the buffer and then wakes up this thread, by which
|
||||
* time another notification (that the time event started)
|
||||
* might already be processed unsuccessfully.
|
||||
*/
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
|
||||
time_event_response,
|
||||
ARRAY_SIZE(time_event_response),
|
||||
iwl_mvm_time_event_response, te_data);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
|
||||
sizeof(*te_cmd), te_cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
|
||||
iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
|
||||
goto out_clear_te;
|
||||
}
|
||||
|
||||
/* No need to wait for anything, so just pass 1 (0 isn't valid) */
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
|
||||
/* should never fail */
|
||||
WARN_ON_ONCE(ret);
|
||||
|
||||
if (ret) {
|
||||
out_clear_te:
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mvm_protect_session(struct iwl_mvm *mvm,
|
||||
@ -278,11 +318,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
|
||||
static const u8 time_event_notif[] = { TIME_EVENT_CMD,
|
||||
TIME_EVENT_NOTIFICATION };
|
||||
struct iwl_notification_wait wait_time_event;
|
||||
struct iwl_time_event_cmd time_cmd = {};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -309,12 +345,6 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
}
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
|
||||
time_event_notif,
|
||||
ARRAY_SIZE(time_event_notif),
|
||||
iwl_mvm_time_event_notif,
|
||||
&mvmvif->time_event_data);
|
||||
|
||||
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
time_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
|
||||
@ -322,6 +352,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
|
||||
|
||||
time_cmd.apply_time =
|
||||
cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG));
|
||||
|
||||
time_cmd.dep_policy = TE_INDEPENDENT;
|
||||
time_cmd.is_present = cpu_to_le32(1);
|
||||
time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE);
|
||||
@ -333,33 +364,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
|
||||
time_cmd.repeat = cpu_to_le32(1);
|
||||
time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
|
||||
|
||||
te_data->vif = vif;
|
||||
te_data->duration = duration;
|
||||
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
te_data->id = le32_to_cpu(time_cmd.id);
|
||||
list_add_tail(&te_data->list, &mvm->time_event_list);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
|
||||
sizeof(time_cmd), &time_cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
|
||||
goto out_remove_notif;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1 * HZ);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "%s - failed on timeout\n", __func__);
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out_remove_notif:
|
||||
iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
|
||||
iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -424,43 +429,12 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
|
||||
iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_roc_te_notif(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(notif_wait, struct iwl_mvm, notif_wait);
|
||||
struct iwl_mvm_time_event_data *te_data = data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
|
||||
struct iwl_time_event_resp *resp;
|
||||
|
||||
u32 mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
|
||||
|
||||
/* until we do something else */
|
||||
WARN_ON(te_data->id != TE_P2P_DEVICE_DISCOVERABLE);
|
||||
|
||||
switch (pkt->hdr.cmd) {
|
||||
case TIME_EVENT_CMD:
|
||||
resp = (void *)pkt->data;
|
||||
WARN_ON(mac_id_n_color != le32_to_cpu(resp->id_and_color));
|
||||
te_data->uid = le32_to_cpu(resp->unique_id);
|
||||
IWL_DEBUG_TE(mvm, "Got response - UID = 0x%x\n", te_data->uid);
|
||||
return true;
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
int duration)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
|
||||
static const u8 roc_te_notif[] = { TIME_EVENT_CMD };
|
||||
struct iwl_notification_wait wait_time_event;
|
||||
struct iwl_time_event_cmd time_cmd = {};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
if (te_data->running) {
|
||||
@ -474,16 +448,10 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
*/
|
||||
flush_work(&mvm->roc_done_wk);
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
|
||||
roc_te_notif,
|
||||
ARRAY_SIZE(roc_te_notif),
|
||||
iwl_mvm_roc_te_notif,
|
||||
&mvmvif->time_event_data);
|
||||
|
||||
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
time_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
|
||||
time_cmd.id = cpu_to_le32(TE_P2P_DEVICE_DISCOVERABLE);
|
||||
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE);
|
||||
|
||||
time_cmd.apply_time = cpu_to_le32(0);
|
||||
time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
|
||||
@ -492,7 +460,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
time_cmd.interval = cpu_to_le32(1);
|
||||
|
||||
/*
|
||||
* TE_P2P_DEVICE_DISCOVERABLE can have lower priority than other events
|
||||
* IWL_MVM_ROC_TE_TYPE can have lower priority than other events
|
||||
* that are being scheduled by the driver/fw, and thus it might not be
|
||||
* scheduled. To improve the chances of it being scheduled, allow it to
|
||||
* be fragmented.
|
||||
@ -505,33 +473,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
time_cmd.repeat = cpu_to_le32(1);
|
||||
time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
|
||||
|
||||
/* Push the te data to the tracked te list */
|
||||
te_data->vif = vif;
|
||||
te_data->duration = MSEC_TO_TU(duration);
|
||||
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
te_data->id = le32_to_cpu(time_cmd.id);
|
||||
list_add_tail(&te_data->list, &mvm->time_event_list);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
|
||||
sizeof(time_cmd), &time_cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
|
||||
goto out_remove_notif;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1 * HZ);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "%s - failed on timeout\n", __func__);
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
out_remove_notif:
|
||||
iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
|
||||
return ret;
|
||||
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
|
||||
}
|
||||
|
||||
void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)
|
||||
|
@ -620,7 +620,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
seq_ctl = le16_to_cpu(hdr->seq_ctrl);
|
||||
}
|
||||
|
||||
ieee80211_tx_status(mvm->hw, skb);
|
||||
ieee80211_tx_status_ni(mvm->hw, skb);
|
||||
}
|
||||
|
||||
if (txq_id >= IWL_FIRST_AMPDU_QUEUE) {
|
||||
@ -663,12 +663,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_tid_data *tid_data =
|
||||
&mvmsta->tid_data[tid];
|
||||
|
||||
spin_lock(&mvmsta->lock);
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
tid_data->next_reclaimed = next_reclaimed;
|
||||
IWL_DEBUG_TX_REPLY(mvm, "Next reclaimed packet:%d\n",
|
||||
next_reclaimed);
|
||||
iwl_mvm_check_ratid_empty(mvm, sta, tid);
|
||||
spin_unlock(&mvmsta->lock);
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@ -832,7 +832,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock(&mvmsta->lock);
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
|
||||
__skb_queue_head_init(&reclaimed_skbs);
|
||||
|
||||
@ -886,13 +886,13 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&mvmsta->lock);
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||
skb = __skb_dequeue(&reclaimed_skbs);
|
||||
ieee80211_tx_status(mvm->hw, skb);
|
||||
ieee80211_tx_status_ni(mvm->hw, skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -249,7 +249,6 @@ struct iwl_trans_pcie {
|
||||
int ict_index;
|
||||
u32 inta;
|
||||
bool use_ict;
|
||||
struct tasklet_struct irq_tasklet;
|
||||
struct isr_statistics isr_stats;
|
||||
|
||||
spinlock_t irq_lock;
|
||||
@ -330,7 +329,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
|
||||
* RX
|
||||
******************************************************/
|
||||
int iwl_pcie_rx_init(struct iwl_trans *trans);
|
||||
void iwl_pcie_tasklet(struct iwl_trans *trans);
|
||||
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id);
|
||||
int iwl_pcie_rx_stop(struct iwl_trans *trans);
|
||||
void iwl_pcie_rx_free(struct iwl_trans *trans);
|
||||
|
||||
|
@ -81,10 +81,10 @@
|
||||
* 'processed' and 'read' driver indexes as well)
|
||||
* + A received packet is processed and handed to the kernel network stack,
|
||||
* detached from the iwl->rxq. The driver 'processed' index is updated.
|
||||
* + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
|
||||
* list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
|
||||
* INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
|
||||
* were enough free buffers and RX_STALLED is set it is cleared.
|
||||
* + The Host/Firmware iwl->rxq is replenished at irq thread time from the
|
||||
* rx_free list. If there are no allocated buffers in iwl->rxq->rx_free,
|
||||
* the READ INDEX is not incremented and iwl->status(RX_STALLED) is set.
|
||||
* If there were enough free buffers and RX_STALLED is set it is cleared.
|
||||
*
|
||||
*
|
||||
* Driver sequence:
|
||||
@ -214,9 +214,9 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
|
||||
/*
|
||||
* If the device isn't enabled - not need to try to add buffers...
|
||||
* This can happen when we stop the device and still have an interrupt
|
||||
* pending. We stop the APM before we sync the interrupts / tasklets
|
||||
* because we have to (see comment there). On the other hand, since
|
||||
* the APM is stopped, we cannot access the HW (in particular not prph).
|
||||
* pending. We stop the APM before we sync the interrupts because we
|
||||
* have to (see comment there). On the other hand, since the APM is
|
||||
* stopped, we cannot access the HW (in particular not prph).
|
||||
* So don't try to restock if the APM has been already stopped.
|
||||
*/
|
||||
if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status))
|
||||
@ -796,11 +796,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
|
||||
wake_up(&trans_pcie->wait_command_queue);
|
||||
|
||||
local_bh_disable();
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
void iwl_pcie_tasklet(struct iwl_trans *trans)
|
||||
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct iwl_trans *trans = dev_id;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
|
||||
u32 inta = 0;
|
||||
@ -811,6 +814,8 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
|
||||
u32 inta_mask;
|
||||
#endif
|
||||
|
||||
lock_map_acquire(&trans->sync_cmd_lockdep_map);
|
||||
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Ack/clear/reset pending uCode interrupts.
|
||||
@ -855,7 +860,7 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
|
||||
|
||||
handled |= CSR_INT_BIT_HW_ERR;
|
||||
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
@ -1005,6 +1010,10 @@ void iwl_pcie_tasklet(struct iwl_trans *trans)
|
||||
/* Re-enable RF_KILL if it occurred */
|
||||
else if (handled & CSR_INT_BIT_RF_KILL)
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
out:
|
||||
lock_map_release(&trans->sync_cmd_lockdep_map);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -1127,7 +1136,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
* If we have something to service, the tasklet will re-enable ints.
|
||||
* If we have something to service, the irq thread will re-enable ints.
|
||||
* If we *don't* have something, we'll re-enable before leaving here. */
|
||||
inta_mask = iwl_read32(trans, CSR_INT_MASK);
|
||||
iwl_write32(trans, CSR_INT_MASK, 0x00000000);
|
||||
@ -1167,9 +1176,9 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
|
||||
#endif
|
||||
|
||||
trans_pcie->inta |= inta;
|
||||
/* iwl_pcie_tasklet() will service interrupts and re-enable them */
|
||||
/* the thread will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&trans_pcie->irq_tasklet);
|
||||
return IRQ_WAKE_THREAD;
|
||||
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
!trans_pcie->inta)
|
||||
iwl_enable_interrupts(trans);
|
||||
@ -1277,9 +1286,10 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
|
||||
trans_pcie->inta |= inta;
|
||||
|
||||
/* iwl_pcie_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&trans_pcie->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
if (likely(inta)) {
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
return IRQ_WAKE_THREAD;
|
||||
} else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
!trans_pcie->inta) {
|
||||
/* Allow interrupt if was disabled by this handler and
|
||||
* no tasklet was schedules, We should not enable interrupt,
|
||||
|
@ -760,7 +760,6 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
synchronize_irq(trans_pcie->pci_dev->irq);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
|
||||
iwl_pcie_tx_free(trans);
|
||||
iwl_pcie_rx_free(trans);
|
||||
@ -1480,6 +1479,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
||||
trans->ops = &trans_ops_pcie;
|
||||
trans->cfg = cfg;
|
||||
trans_lockdep_init(trans);
|
||||
trans_pcie->trans = trans;
|
||||
spin_lock_init(&trans_pcie->irq_lock);
|
||||
spin_lock_init(&trans_pcie->reg_lock);
|
||||
@ -1567,15 +1567,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
||||
trans_pcie->inta_mask = CSR_INI_SET_MASK;
|
||||
|
||||
tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
|
||||
iwl_pcie_tasklet, (unsigned long)trans);
|
||||
|
||||
if (iwl_pcie_alloc_ict(trans))
|
||||
goto out_free_cmd_pool;
|
||||
|
||||
err = request_irq(pdev->irq, iwl_pcie_isr_ict,
|
||||
IRQF_SHARED, DRV_NAME, trans);
|
||||
if (err) {
|
||||
if (request_threaded_irq(pdev->irq, iwl_pcie_isr_ict,
|
||||
iwl_pcie_irq_handler,
|
||||
IRQF_SHARED, DRV_NAME, trans)) {
|
||||
IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq);
|
||||
goto out_free_ict;
|
||||
}
|
||||
|
@ -926,7 +926,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||
if (WARN_ON(txq_id == trans_pcie->cmd_queue))
|
||||
return;
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
spin_lock_bh(&txq->lock);
|
||||
|
||||
if (txq->q.read_ptr == tfd_num)
|
||||
goto out;
|
||||
@ -970,7 +970,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||
if (iwl_queue_space(&txq->q) > txq->q.low_mark)
|
||||
iwl_wake_queue(trans, txq);
|
||||
out:
|
||||
spin_unlock(&txq->lock);
|
||||
spin_unlock_bh(&txq->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1371,7 +1371,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
spin_lock_bh(&txq->lock);
|
||||
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
cmd = txq->entries[cmd_index].cmd;
|
||||
@ -1405,7 +1405,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
|
||||
|
||||
meta->flags = 0;
|
||||
|
||||
spin_unlock(&txq->lock);
|
||||
spin_unlock_bh(&txq->lock);
|
||||
}
|
||||
|
||||
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
|
||||
|
@ -657,7 +657,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
|
||||
capa, intvl, ie, ielen,
|
||||
LBS_SCAN_RSSI_TO_MBM(rssi),
|
||||
GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
}
|
||||
} else
|
||||
lbs_deb_scan("scan response: missing BSS channel IE\n");
|
||||
@ -1444,7 +1444,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
done:
|
||||
if (bss)
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -1766,7 +1766,7 @@ static void lbs_join_post(struct lbs_private *priv,
|
||||
params->beacon_interval,
|
||||
fake_ie, fake - fake_ie,
|
||||
0, GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->wdev->wiphy, bss);
|
||||
|
||||
memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
|
||||
priv->wdev->ssid_len = params->ssid_len;
|
||||
@ -2011,7 +2011,7 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
if (bss) {
|
||||
ret = lbs_ibss_join_existing(priv, params, bss);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
} else
|
||||
ret = lbs_ibss_start_new(priv, params);
|
||||
|
||||
|
@ -2247,6 +2247,7 @@ static int __init init_mac80211_hwsim(void)
|
||||
/* ask mac80211 to reserve space for magic */
|
||||
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
|
||||
hw->sta_data_size = sizeof(struct hwsim_sta_priv);
|
||||
hw->chanctx_data_size = sizeof(struct hwsim_chanctx_priv);
|
||||
|
||||
memcpy(data->channels_2ghz, hwsim_channels_2ghz,
|
||||
sizeof(hwsim_channels_2ghz));
|
||||
|
@ -20,12 +20,12 @@ config MWIFIEX_SDIO
|
||||
mwifiex_sdio.
|
||||
|
||||
config MWIFIEX_PCIE
|
||||
tristate "Marvell WiFi-Ex Driver for PCIE 8766"
|
||||
tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897"
|
||||
depends on MWIFIEX && PCI
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This adds support for wireless adapters based on Marvell
|
||||
8766 chipset with PCIe interface.
|
||||
8766/8897 chipsets with PCIe interface.
|
||||
|
||||
If you choose to build it as a module, it will be called
|
||||
mwifiex_pcie.
|
||||
|
@ -1430,7 +1430,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
|
||||
bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
|
||||
bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
|
||||
0, ie_buf, ie_len, 0, GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->wdev->wiphy, bss);
|
||||
memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
|
||||
|
||||
return 0;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,11 @@
|
||||
#include "main.h"
|
||||
|
||||
#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
|
||||
#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin"
|
||||
|
||||
#define PCIE_VENDOR_ID_MARVELL (0x11ab)
|
||||
#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30)
|
||||
#define PCIE_DEVICE_ID_MARVELL_88W8897 (0x2b38)
|
||||
|
||||
/* Constants for Buffer Descriptor (BD) rings */
|
||||
#define MWIFIEX_MAX_TXRX_BD 0x20
|
||||
@ -57,6 +62,8 @@
|
||||
#define PCIE_SCRATCH_10_REG 0xCE8
|
||||
#define PCIE_SCRATCH_11_REG 0xCEC
|
||||
#define PCIE_SCRATCH_12_REG 0xCF0
|
||||
#define PCIE_RD_DATA_PTR_Q0_Q1 0xC08C
|
||||
#define PCIE_WR_DATA_PTR_Q0_Q1 0xC05C
|
||||
|
||||
#define CPU_INTR_DNLD_RDY BIT(0)
|
||||
#define CPU_INTR_DOOR_BELL BIT(1)
|
||||
@ -75,27 +82,14 @@
|
||||
#define MWIFIEX_BD_FLAG_ROLLOVER_IND BIT(7)
|
||||
#define MWIFIEX_BD_FLAG_FIRST_DESC BIT(0)
|
||||
#define MWIFIEX_BD_FLAG_LAST_DESC BIT(1)
|
||||
#define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG
|
||||
#define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG
|
||||
#define REG_CMD_SIZE PCIE_SCRATCH_2_REG
|
||||
|
||||
#define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG
|
||||
#define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG
|
||||
|
||||
/* TX buffer description read pointer */
|
||||
#define REG_TXBD_RDPTR PCIE_SCRATCH_6_REG
|
||||
/* TX buffer description write pointer */
|
||||
#define REG_TXBD_WRPTR PCIE_SCRATCH_7_REG
|
||||
/* RX buffer description read pointer */
|
||||
#define REG_RXBD_RDPTR PCIE_SCRATCH_8_REG
|
||||
/* RX buffer description write pointer */
|
||||
#define REG_RXBD_WRPTR PCIE_SCRATCH_9_REG
|
||||
/* Event buffer description read pointer */
|
||||
#define REG_EVTBD_RDPTR PCIE_SCRATCH_10_REG
|
||||
/* Event buffer description write pointer */
|
||||
#define REG_EVTBD_WRPTR PCIE_SCRATCH_11_REG
|
||||
/* Driver ready signature write pointer */
|
||||
#define REG_DRV_READY PCIE_SCRATCH_12_REG
|
||||
#define MWIFIEX_BD_FLAG_SOP BIT(0)
|
||||
#define MWIFIEX_BD_FLAG_EOP BIT(1)
|
||||
#define MWIFIEX_BD_FLAG_XS_SOP BIT(2)
|
||||
#define MWIFIEX_BD_FLAG_XS_EOP BIT(3)
|
||||
#define MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND BIT(7)
|
||||
#define MWIFIEX_BD_FLAG_RX_ROLLOVER_IND BIT(10)
|
||||
#define MWIFIEX_BD_FLAG_TX_START_PTR BIT(16)
|
||||
#define MWIFIEX_BD_FLAG_TX_ROLLOVER_IND BIT(26)
|
||||
|
||||
/* Max retry number of command write */
|
||||
#define MAX_WRITE_IOMEM_RETRY 2
|
||||
@ -104,15 +98,142 @@
|
||||
/* FW awake cookie after FW ready */
|
||||
#define FW_AWAKE_COOKIE (0xAA55AA55)
|
||||
|
||||
struct mwifiex_pcie_card_reg {
|
||||
u16 cmd_addr_lo;
|
||||
u16 cmd_addr_hi;
|
||||
u16 fw_status;
|
||||
u16 cmd_size;
|
||||
u16 cmdrsp_addr_lo;
|
||||
u16 cmdrsp_addr_hi;
|
||||
u16 tx_rdptr;
|
||||
u16 tx_wrptr;
|
||||
u16 rx_rdptr;
|
||||
u16 rx_wrptr;
|
||||
u16 evt_rdptr;
|
||||
u16 evt_wrptr;
|
||||
u16 drv_rdy;
|
||||
u16 tx_start_ptr;
|
||||
u32 tx_mask;
|
||||
u32 tx_wrap_mask;
|
||||
u32 rx_mask;
|
||||
u32 rx_wrap_mask;
|
||||
u32 tx_rollover_ind;
|
||||
u32 rx_rollover_ind;
|
||||
u32 evt_rollover_ind;
|
||||
u8 ring_flag_sop;
|
||||
u8 ring_flag_eop;
|
||||
u8 ring_flag_xs_sop;
|
||||
u8 ring_flag_xs_eop;
|
||||
u32 ring_tx_start_ptr;
|
||||
u8 pfu_enabled;
|
||||
u8 sleep_cookie;
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = {
|
||||
.cmd_addr_lo = PCIE_SCRATCH_0_REG,
|
||||
.cmd_addr_hi = PCIE_SCRATCH_1_REG,
|
||||
.cmd_size = PCIE_SCRATCH_2_REG,
|
||||
.fw_status = PCIE_SCRATCH_3_REG,
|
||||
.cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
|
||||
.cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
|
||||
.tx_rdptr = PCIE_SCRATCH_6_REG,
|
||||
.tx_wrptr = PCIE_SCRATCH_7_REG,
|
||||
.rx_rdptr = PCIE_SCRATCH_8_REG,
|
||||
.rx_wrptr = PCIE_SCRATCH_9_REG,
|
||||
.evt_rdptr = PCIE_SCRATCH_10_REG,
|
||||
.evt_wrptr = PCIE_SCRATCH_11_REG,
|
||||
.drv_rdy = PCIE_SCRATCH_12_REG,
|
||||
.tx_start_ptr = 0,
|
||||
.tx_mask = MWIFIEX_TXBD_MASK,
|
||||
.tx_wrap_mask = 0,
|
||||
.rx_mask = MWIFIEX_RXBD_MASK,
|
||||
.rx_wrap_mask = 0,
|
||||
.tx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
|
||||
.rx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
|
||||
.evt_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
|
||||
.ring_flag_sop = 0,
|
||||
.ring_flag_eop = 0,
|
||||
.ring_flag_xs_sop = 0,
|
||||
.ring_flag_xs_eop = 0,
|
||||
.ring_tx_start_ptr = 0,
|
||||
.pfu_enabled = 0,
|
||||
.sleep_cookie = 1,
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = {
|
||||
.cmd_addr_lo = PCIE_SCRATCH_0_REG,
|
||||
.cmd_addr_hi = PCIE_SCRATCH_1_REG,
|
||||
.cmd_size = PCIE_SCRATCH_2_REG,
|
||||
.fw_status = PCIE_SCRATCH_3_REG,
|
||||
.cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
|
||||
.cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
|
||||
.tx_rdptr = PCIE_RD_DATA_PTR_Q0_Q1,
|
||||
.tx_wrptr = PCIE_WR_DATA_PTR_Q0_Q1,
|
||||
.rx_rdptr = PCIE_WR_DATA_PTR_Q0_Q1,
|
||||
.rx_wrptr = PCIE_RD_DATA_PTR_Q0_Q1,
|
||||
.evt_rdptr = PCIE_SCRATCH_10_REG,
|
||||
.evt_wrptr = PCIE_SCRATCH_11_REG,
|
||||
.drv_rdy = PCIE_SCRATCH_12_REG,
|
||||
.tx_start_ptr = 16,
|
||||
.tx_mask = 0x03FF0000,
|
||||
.tx_wrap_mask = 0x07FF0000,
|
||||
.rx_mask = 0x000003FF,
|
||||
.rx_wrap_mask = 0x000007FF,
|
||||
.tx_rollover_ind = MWIFIEX_BD_FLAG_TX_ROLLOVER_IND,
|
||||
.rx_rollover_ind = MWIFIEX_BD_FLAG_RX_ROLLOVER_IND,
|
||||
.evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
|
||||
.ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
|
||||
.ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
|
||||
.ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
|
||||
.ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
|
||||
.ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
|
||||
.pfu_enabled = 1,
|
||||
.sleep_cookie = 0,
|
||||
};
|
||||
|
||||
struct mwifiex_pcie_device {
|
||||
const char *firmware;
|
||||
const struct mwifiex_pcie_card_reg *reg;
|
||||
u16 blksz_fw_dl;
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
|
||||
.firmware = PCIE8766_DEFAULT_FW_NAME,
|
||||
.reg = &mwifiex_reg_8766,
|
||||
.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
|
||||
.firmware = PCIE8897_DEFAULT_FW_NAME,
|
||||
.reg = &mwifiex_reg_8897,
|
||||
.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
|
||||
};
|
||||
|
||||
struct mwifiex_evt_buf_desc {
|
||||
u64 paddr;
|
||||
u16 len;
|
||||
u16 flags;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_pcie_buf_desc {
|
||||
u64 paddr;
|
||||
u16 len;
|
||||
u16 flags;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_pfu_buf_desc {
|
||||
u16 flags;
|
||||
u16 offset;
|
||||
u16 frag_len;
|
||||
u16 len;
|
||||
u64 paddr;
|
||||
u32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct pcie_service_card {
|
||||
struct pci_dev *dev;
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct mwifiex_pcie_device pcie;
|
||||
|
||||
u8 txbd_flush;
|
||||
u32 txbd_wrptr;
|
||||
@ -120,7 +241,7 @@ struct pcie_service_card {
|
||||
u32 txbd_ring_size;
|
||||
u8 *txbd_ring_vbase;
|
||||
dma_addr_t txbd_ring_pbase;
|
||||
struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
void *txbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD];
|
||||
|
||||
u32 rxbd_wrptr;
|
||||
@ -128,7 +249,7 @@ struct pcie_service_card {
|
||||
u32 rxbd_ring_size;
|
||||
u8 *rxbd_ring_vbase;
|
||||
dma_addr_t rxbd_ring_pbase;
|
||||
struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
void *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD];
|
||||
|
||||
u32 evtbd_wrptr;
|
||||
@ -136,7 +257,7 @@ struct pcie_service_card {
|
||||
u32 evtbd_ring_size;
|
||||
u8 *evtbd_ring_vbase;
|
||||
dma_addr_t evtbd_ring_pbase;
|
||||
struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD];
|
||||
void *evtbd_ring[MWIFIEX_MAX_EVT_BD];
|
||||
struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD];
|
||||
|
||||
struct sk_buff *cmd_buf;
|
||||
@ -150,11 +271,24 @@ struct pcie_service_card {
|
||||
static inline int
|
||||
mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
|
||||
{
|
||||
if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) ==
|
||||
(rdptr & MWIFIEX_TXBD_MASK)) &&
|
||||
((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
|
||||
(rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND)))
|
||||
return 1;
|
||||
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
|
||||
|
||||
switch (card->dev->device) {
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8766P:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) ==
|
||||
(rdptr & reg->tx_mask)) &&
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) !=
|
||||
(rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8897:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) ==
|
||||
(rdptr & reg->tx_mask)) &&
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) ==
|
||||
(rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -162,11 +296,24 @@ mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
|
||||
static inline int
|
||||
mwifiex_pcie_txbd_not_full(struct pcie_service_card *card)
|
||||
{
|
||||
if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) !=
|
||||
(card->txbd_rdptr & MWIFIEX_TXBD_MASK)) ||
|
||||
((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
|
||||
(card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND)))
|
||||
return 1;
|
||||
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
|
||||
|
||||
switch (card->dev->device) {
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8766P:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) !=
|
||||
(card->txbd_rdptr & reg->tx_mask)) ||
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) !=
|
||||
(card->txbd_rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8897:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) !=
|
||||
(card->txbd_rdptr & reg->tx_mask)) ||
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) ==
|
||||
(card->txbd_rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1741,7 +1741,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||
.mac_address, ETH_ALEN))
|
||||
mwifiex_update_curr_bss_params(priv,
|
||||
bss);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->wdev->wiphy, bss);
|
||||
}
|
||||
} else {
|
||||
dev_dbg(adapter->dev, "missing BSS channel IE\n");
|
||||
|
@ -162,13 +162,9 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
||||
|
||||
rcu_read_lock();
|
||||
ies = rcu_dereference(bss->ies);
|
||||
if (WARN_ON(!ies)) {
|
||||
/* should never happen */
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
|
||||
beacon_ie_len = ies->len;
|
||||
bss_desc->timestamp = ies->tsf;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!beacon_ie) {
|
||||
@ -184,7 +180,6 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
||||
bss_desc->cap_info_bitmap = bss->capability;
|
||||
bss_desc->bss_band = bss_priv->band;
|
||||
bss_desc->fw_tsf = bss_priv->fw_tsf;
|
||||
bss_desc->timestamp = bss->tsf;
|
||||
if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
|
||||
dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
|
||||
bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
|
||||
@ -322,7 +317,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
||||
}
|
||||
|
||||
if (bss)
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->adapter->wiphy, bss);
|
||||
} else {
|
||||
/* Adhoc mode */
|
||||
/* If the requested SSID matches current SSID, return */
|
||||
@ -352,7 +347,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
||||
" list. Joining...\n");
|
||||
ret = mwifiex_adhoc_join(priv, bss_desc);
|
||||
if (bss)
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->adapter->wiphy, bss);
|
||||
} else {
|
||||
dev_dbg(adapter->dev, "info: Network not found in "
|
||||
"the list, creating adhoc with ssid = %s\n",
|
||||
|
@ -5471,6 +5471,8 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
|
||||
{ },
|
||||
};
|
||||
|
@ -125,7 +125,7 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv,
|
||||
cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp,
|
||||
capability, beacon_interval, ie_buf, ie_len,
|
||||
signal, GFP_KERNEL);
|
||||
cfg80211_put_bss(cbss);
|
||||
cfg80211_put_bss(wiphy, cbss);
|
||||
}
|
||||
|
||||
void orinoco_add_extscan_result(struct orinoco_private *priv,
|
||||
@ -158,7 +158,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
|
||||
cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp,
|
||||
capability, beacon_interval, ie, ie_len,
|
||||
signal, GFP_KERNEL);
|
||||
cfg80211_put_bss(cbss);
|
||||
cfg80211_put_bss(wiphy, cbss);
|
||||
}
|
||||
|
||||
void orinoco_add_hostscan_results(struct orinoco_private *priv,
|
||||
|
@ -84,8 +84,8 @@ static struct usb_device_id p54u_table[] = {
|
||||
{USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
|
||||
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
|
||||
{USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */
|
||||
{USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */
|
||||
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
|
||||
{USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */
|
||||
{USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */
|
||||
{USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
|
||||
{USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
|
||||
|
@ -2026,7 +2026,7 @@ static bool rndis_bss_info_update(struct usbnet *usbdev,
|
||||
bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac,
|
||||
timestamp, capability, beacon_interval, ie, ie_len, signal,
|
||||
GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->wdev.wiphy, bss);
|
||||
|
||||
return (bss != NULL);
|
||||
}
|
||||
@ -2715,7 +2715,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
|
||||
bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid,
|
||||
timestamp, capability, beacon_period, ie_buf, ie_len,
|
||||
signal, GFP_KERNEL);
|
||||
cfg80211_put_bss(bss);
|
||||
cfg80211_put_bss(priv->wdev.wiphy, bss);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1185,8 +1185,14 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
|
||||
rt2x00queue_map_txskb(entry);
|
||||
|
||||
if (rt2x00queue_map_txskb(entry)) {
|
||||
ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Enable beaconing again.
|
||||
*/
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
|
||||
/*
|
||||
* Write the TX descriptor for the beacon.
|
||||
*/
|
||||
@ -1196,7 +1202,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
|
||||
out:
|
||||
/*
|
||||
* Enable beaconing again.
|
||||
*/
|
||||
|
@ -1338,7 +1338,10 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
|
||||
rt2x00queue_map_txskb(entry);
|
||||
if (rt2x00queue_map_txskb(entry)) {
|
||||
ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the TX descriptor for the beacon.
|
||||
@ -1349,7 +1352,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
|
||||
out:
|
||||
/*
|
||||
* Enable beaconing again.
|
||||
*/
|
||||
|
@ -1099,9 +1099,11 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x15a9, 0x0006) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0153) },
|
||||
{ USB_DEVICE(0x177f, 0x0164) },
|
||||
{ USB_DEVICE(0x177f, 0x0302) },
|
||||
{ USB_DEVICE(0x177f, 0x0313) },
|
||||
{ USB_DEVICE(0x177f, 0x0323) },
|
||||
{ USB_DEVICE(0x177f, 0x0324) },
|
||||
/* U-Media */
|
||||
{ USB_DEVICE(0x157e, 0x300e) },
|
||||
{ USB_DEVICE(0x157e, 0x3013) },
|
||||
@ -1133,6 +1135,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x148f, 0x8070) },
|
||||
/* Sitecom */
|
||||
{ USB_DEVICE(0x0df6, 0x0050) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0163) },
|
||||
{ USB_DEVICE(0x177f, 0x0165) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800USB_RT35XX
|
||||
/* Allwin */
|
||||
@ -1214,10 +1219,15 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x0b05, 0x1760) },
|
||||
{ USB_DEVICE(0x0b05, 0x1761) },
|
||||
{ USB_DEVICE(0x0b05, 0x1790) },
|
||||
{ USB_DEVICE(0x0b05, 0x17a7) },
|
||||
/* AzureWave */
|
||||
{ USB_DEVICE(0x13d3, 0x3262) },
|
||||
{ USB_DEVICE(0x13d3, 0x3284) },
|
||||
{ USB_DEVICE(0x13d3, 0x3322) },
|
||||
{ USB_DEVICE(0x13d3, 0x3340) },
|
||||
{ USB_DEVICE(0x13d3, 0x3399) },
|
||||
{ USB_DEVICE(0x13d3, 0x3400) },
|
||||
{ USB_DEVICE(0x13d3, 0x3401) },
|
||||
/* Belkin */
|
||||
{ USB_DEVICE(0x050d, 0x1003) },
|
||||
/* Buffalo */
|
||||
@ -1232,10 +1242,15 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x07d1, 0x3c0b) },
|
||||
/* Encore */
|
||||
{ USB_DEVICE(0x203d, 0x14a1) },
|
||||
/* EnGenius */
|
||||
{ USB_DEVICE(0x1740, 0x0600) },
|
||||
{ USB_DEVICE(0x1740, 0x0602) },
|
||||
/* Gemtek */
|
||||
{ USB_DEVICE(0x15a9, 0x0010) },
|
||||
/* Gigabyte */
|
||||
{ USB_DEVICE(0x1044, 0x800c) },
|
||||
/* Hercules */
|
||||
{ USB_DEVICE(0x06f8, 0xe036) },
|
||||
/* Huawei */
|
||||
{ USB_DEVICE(0x148f, 0xf101) },
|
||||
/* I-O DATA */
|
||||
@ -1262,11 +1277,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x0df6, 0x004a) },
|
||||
{ USB_DEVICE(0x0df6, 0x004d) },
|
||||
{ USB_DEVICE(0x0df6, 0x0053) },
|
||||
{ USB_DEVICE(0x0df6, 0x0069) },
|
||||
{ USB_DEVICE(0x0df6, 0x006f) },
|
||||
/* SMC */
|
||||
{ USB_DEVICE(0x083a, 0xa512) },
|
||||
{ USB_DEVICE(0x083a, 0xc522) },
|
||||
{ USB_DEVICE(0x083a, 0xd522) },
|
||||
{ USB_DEVICE(0x083a, 0xf511) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0254) },
|
||||
/* TP-LINK */
|
||||
{ USB_DEVICE(0xf201, 0x5370) },
|
||||
#endif
|
||||
{ 0, }
|
||||
};
|
||||
|
@ -1169,8 +1169,10 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
|
||||
/**
|
||||
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
|
||||
* @entry: Pointer to &struct queue_entry
|
||||
*
|
||||
* Returns -ENOMEM if mapping fail, 0 otherwise.
|
||||
*/
|
||||
void rt2x00queue_map_txskb(struct queue_entry *entry);
|
||||
int rt2x00queue_map_txskb(struct queue_entry *entry);
|
||||
|
||||
/**
|
||||
* rt2x00queue_unmap_skb - Unmap a skb from DMA.
|
||||
|
@ -87,24 +87,35 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
|
||||
skbdesc->entry = entry;
|
||||
|
||||
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
|
||||
skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
|
||||
skb->data,
|
||||
skb->len,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_addr_t skb_dma;
|
||||
|
||||
skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
|
||||
DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(rt2x00dev->dev, skb_dma))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
skbdesc->skb_dma = skb_dma;
|
||||
skbdesc->flags |= SKBDESC_DMA_MAPPED_RX;
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
void rt2x00queue_map_txskb(struct queue_entry *entry)
|
||||
int rt2x00queue_map_txskb(struct queue_entry *entry)
|
||||
{
|
||||
struct device *dev = entry->queue->rt2x00dev->dev;
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
|
||||
skbdesc->skb_dma =
|
||||
dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE);
|
||||
|
||||
if (unlikely(dma_mapping_error(dev, skbdesc->skb_dma)))
|
||||
return -ENOMEM;
|
||||
|
||||
skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
|
||||
|
||||
@ -343,10 +354,7 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
|
||||
* when using more then one tx stream (>MCS7).
|
||||
*/
|
||||
if (sta && txdesc->u.ht.mcs > 7 &&
|
||||
((sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SM_PS) >>
|
||||
IEEE80211_HT_CAP_SM_PS_SHIFT) ==
|
||||
WLAN_HT_CAP_SM_PS_DYNAMIC)
|
||||
sta->smps_mode == IEEE80211_SMPS_DYNAMIC)
|
||||
__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
|
||||
} else {
|
||||
txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
|
||||
@ -545,8 +553,9 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
|
||||
/*
|
||||
* Map the skb to DMA.
|
||||
*/
|
||||
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
|
||||
rt2x00queue_map_txskb(entry);
|
||||
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags) &&
|
||||
rt2x00queue_map_txskb(entry))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +1,26 @@
|
||||
config RTLWIFI
|
||||
tristate "Realtek wireless card support"
|
||||
depends on MAC80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This is common code for RTL8192CE/RTL8192CU/RTL8192SE/RTL8723AE
|
||||
drivers. This module does nothing by itself - the various front-end
|
||||
drivers need to be enabled to support any desired devices.
|
||||
|
||||
If you choose to build as a module, it'll be called rtlwifi.
|
||||
|
||||
config RTLWIFI_DEBUG
|
||||
bool "Debugging output for rtlwifi driver family"
|
||||
depends on RTLWIFI
|
||||
default y
|
||||
---help---
|
||||
To use the module option that sets the dynamic-debugging level for,
|
||||
the front-end driver, this parameter must be "Y". For memory-limited
|
||||
systems, choose "N". If in doubt, choose "Y".
|
||||
|
||||
config RTL8192CE
|
||||
tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter"
|
||||
depends on MAC80211 && PCI
|
||||
select FW_LOADER
|
||||
select RTLWIFI
|
||||
depends on RTLWIFI && PCI
|
||||
select RTL8192C_COMMON
|
||||
---help---
|
||||
This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe
|
||||
@ -12,9 +30,7 @@ config RTL8192CE
|
||||
|
||||
config RTL8192SE
|
||||
tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter"
|
||||
depends on MAC80211 && PCI
|
||||
select FW_LOADER
|
||||
select RTLWIFI
|
||||
depends on RTLWIFI && PCI
|
||||
---help---
|
||||
This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe
|
||||
wireless network adapters.
|
||||
@ -23,9 +39,7 @@ config RTL8192SE
|
||||
|
||||
config RTL8192DE
|
||||
tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
|
||||
depends on MAC80211 && PCI
|
||||
select FW_LOADER
|
||||
select RTLWIFI
|
||||
depends on RTLWIFI && PCI
|
||||
---help---
|
||||
This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
|
||||
wireless network adapters.
|
||||
@ -34,9 +48,7 @@ config RTL8192DE
|
||||
|
||||
config RTL8723AE
|
||||
tristate "Realtek RTL8723AE PCIe Wireless Network Adapter"
|
||||
depends on MAC80211 && PCI && EXPERIMENTAL
|
||||
select FW_LOADER
|
||||
select RTLWIFI
|
||||
depends on RTLWIFI && PCI
|
||||
---help---
|
||||
This is the driver for Realtek RTL8723AE 802.11n PCIe
|
||||
wireless network adapters.
|
||||
@ -45,9 +57,7 @@ config RTL8723AE
|
||||
|
||||
config RTL8192CU
|
||||
tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
|
||||
depends on MAC80211 && USB
|
||||
select FW_LOADER
|
||||
select RTLWIFI
|
||||
depends on RTLWIFI && USB
|
||||
select RTL8192C_COMMON
|
||||
---help---
|
||||
This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB
|
||||
@ -55,16 +65,6 @@ config RTL8192CU
|
||||
|
||||
If you choose to build it as a module, it will be called rtl8192cu
|
||||
|
||||
config RTLWIFI
|
||||
tristate
|
||||
depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE
|
||||
default m
|
||||
|
||||
config RTLWIFI_DEBUG
|
||||
bool "Additional debugging output"
|
||||
depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE
|
||||
default y
|
||||
|
||||
config RTL8192C_COMMON
|
||||
tristate
|
||||
depends on RTL8192CE || RTL8192CU
|
||||
|
@ -523,8 +523,8 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
|
||||
if (mac->opmode == NL80211_IFTYPE_STATION)
|
||||
bw_40 = mac->bw_40;
|
||||
else if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC)
|
||||
bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC)
|
||||
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
|
||||
if (bw_40 && sgi_40)
|
||||
tcb_desc->use_shortgi = true;
|
||||
@ -634,8 +634,7 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
|
||||
return;
|
||||
if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (!(sta->ht_cap.ht_supported) ||
|
||||
!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
return;
|
||||
} else if (mac->opmode == NL80211_IFTYPE_STATION) {
|
||||
if (!mac->bw_40 || !(sta->ht_cap.ht_supported))
|
||||
|
@ -116,9 +116,8 @@ static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv,
|
||||
if (txrc->short_preamble)
|
||||
rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
|
||||
if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (sta && (sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (sta && (sta->bandwidth >= IEEE80211_STA_RX_BW_40))
|
||||
rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
} else {
|
||||
if (mac->bw_40)
|
||||
@ -217,6 +216,12 @@ static void rtl_tx_status(void *ppriv,
|
||||
}
|
||||
}
|
||||
|
||||
static void rtl_rate_init(void *ppriv,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct ieee80211_sta *sta, void *priv_sta)
|
||||
{
|
||||
}
|
||||
|
||||
static void *rtl_rate_alloc(struct ieee80211_hw *hw,
|
||||
struct dentry *debugfsdir)
|
||||
{
|
||||
@ -261,6 +266,7 @@ static struct rate_control_ops rtl_rate_ops = {
|
||||
.free = rtl_rate_free,
|
||||
.alloc_sta = rtl_rate_alloc_sta,
|
||||
.free_sta = rtl_rate_free_sta,
|
||||
.rate_init = rtl_rate_init,
|
||||
.tx_status = rtl_tx_status,
|
||||
.get_rate = rtl_get_rate,
|
||||
};
|
||||
|
@ -1846,9 +1846,9 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
|
||||
struct rtl_sta_info *sta_entry = NULL;
|
||||
u32 ratr_bitmap;
|
||||
u8 ratr_index;
|
||||
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
|
||||
? 1 : 0;
|
||||
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
|
||||
u8 curshortgi_40mhz = curtxbw_40mhz &&
|
||||
(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
1 : 0;
|
||||
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
|
||||
1 : 0;
|
||||
|
@ -488,7 +488,7 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
|
||||
u8 *praddr;
|
||||
__le16 fc;
|
||||
u16 type, c_fc;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon = false;
|
||||
|
||||
tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
|
||||
|
||||
@ -626,8 +626,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
|
||||
} else if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (sta)
|
||||
bw_40 = sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
}
|
||||
|
||||
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
||||
|
@ -1084,7 +1084,7 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
|
||||
u8 *praddr;
|
||||
__le16 fc;
|
||||
u16 type, cpu_fc;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon = false;
|
||||
|
||||
tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
|
||||
hdr = (struct ieee80211_hdr *)tmp_buf;
|
||||
|
@ -285,6 +285,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
|
||||
/* RTL8188CUS-VL */
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)},
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)},
|
||||
/* 8188 Combo for BC4 */
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
|
||||
|
||||
@ -363,9 +364,15 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids);
|
||||
|
||||
static int rtl8192cu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg);
|
||||
}
|
||||
|
||||
static struct usb_driver rtl8192cu_driver = {
|
||||
.name = "rtl8192cu",
|
||||
.probe = rtl_usb_probe,
|
||||
.probe = rtl8192cu_probe,
|
||||
.disconnect = rtl_usb_disconnect,
|
||||
.id_table = rtl8192c_usb_ids,
|
||||
|
||||
|
@ -1970,8 +1970,7 @@ static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw,
|
||||
struct rtl_sta_info *sta_entry = NULL;
|
||||
u32 ratr_bitmap;
|
||||
u8 ratr_index;
|
||||
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
|
||||
? 1 : 0;
|
||||
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
|
||||
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
1 : 0;
|
||||
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
|
||||
|
@ -574,8 +574,7 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
|
||||
} else if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (sta)
|
||||
bw_40 = sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
}
|
||||
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
||||
rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
|
||||
|
@ -2085,8 +2085,7 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
|
||||
struct rtl_sta_info *sta_entry = NULL;
|
||||
u32 ratr_bitmap;
|
||||
u8 ratr_index = 0;
|
||||
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
|
||||
? 1 : 0;
|
||||
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
|
||||
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
1 : 0;
|
||||
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
|
||||
|
@ -621,8 +621,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
|
||||
} else if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (sta)
|
||||
bw_40 = sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
}
|
||||
|
||||
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
||||
|
@ -1866,8 +1866,7 @@ static void rtl8723ae_update_hal_rate_mask(struct ieee80211_hw *hw,
|
||||
struct rtl_sta_info *sta_entry = NULL;
|
||||
u32 ratr_bitmap;
|
||||
u8 ratr_index;
|
||||
u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
|
||||
? 1 : 0;
|
||||
u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
|
||||
u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
1 : 0;
|
||||
u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
|
||||
|
@ -395,8 +395,7 @@ void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
|
||||
} else if (mac->opmode == NL80211_IFTYPE_AP ||
|
||||
mac->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (sta)
|
||||
bw_40 = sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
|
||||
}
|
||||
|
||||
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
||||
|
@ -937,7 +937,8 @@ static struct rtl_intf_ops rtl_usb_ops = {
|
||||
};
|
||||
|
||||
int rtl_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
const struct usb_device_id *id,
|
||||
struct rtl_hal_cfg *rtl_hal_cfg)
|
||||
{
|
||||
int err;
|
||||
struct ieee80211_hw *hw = NULL;
|
||||
@ -972,7 +973,7 @@ int rtl_usb_probe(struct usb_interface *intf,
|
||||
usb_set_intfdata(intf, hw);
|
||||
/* init cfg & intf_ops */
|
||||
rtlpriv->rtlhal.interface = INTF_USB;
|
||||
rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info);
|
||||
rtlpriv->cfg = rtl_hal_cfg;
|
||||
rtlpriv->intf_ops = &rtl_usb_ops;
|
||||
rtl_dbgp_flag_init(hw);
|
||||
/* Init IO handler */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user