forked from luck/tmp_suning_uos_patched
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem
This commit is contained in:
commit
8e2a89c515
|
@ -57,7 +57,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
|||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
|
||||
{0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
|
||||
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
|
||||
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
|
||||
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
|
||||
|
@ -96,7 +96,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
|||
{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
|
||||
{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
|
||||
{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
|
||||
{0x0000ae20, 0x000001a6, 0x000001a6, 0x000001aa, 0x000001aa},
|
||||
{0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
|
||||
};
|
||||
|
||||
|
|
|
@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
|
|||
bool ath9k_hw_check_alive(struct ath_hw *ah)
|
||||
{
|
||||
int count = 50;
|
||||
u32 reg;
|
||||
u32 reg, last_val;
|
||||
|
||||
if (AR_SREV_9300(ah))
|
||||
return !ath9k_hw_detect_mac_hang(ah);
|
||||
|
@ -1542,9 +1542,13 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
|
|||
if (AR_SREV_9285_12_OR_LATER(ah))
|
||||
return true;
|
||||
|
||||
last_val = REG_READ(ah, AR_OBS_BUS_1);
|
||||
do {
|
||||
reg = REG_READ(ah, AR_OBS_BUS_1);
|
||||
if (reg != last_val)
|
||||
return true;
|
||||
|
||||
last_val = reg;
|
||||
if ((reg & 0x7E7FFFEF) == 0x00702400)
|
||||
continue;
|
||||
|
||||
|
@ -1556,6 +1560,8 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
|
|||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
udelay(1);
|
||||
} while (count-- > 0);
|
||||
|
||||
return false;
|
||||
|
|
|
@ -731,6 +731,12 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
|
|||
if (ret == -EINPROGRESS)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Re-check previous descriptor, in case it has been filled
|
||||
* in the mean time.
|
||||
*/
|
||||
ret = ath9k_hw_rxprocdesc(ah, ds, rs);
|
||||
if (ret == -EINPROGRESS) {
|
||||
/*
|
||||
* mark descriptor as zero-length and set the 'more'
|
||||
* flag to ensure that both buffers get discarded
|
||||
|
@ -738,6 +744,7 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
|
|||
rs->rs_datalen = 0;
|
||||
rs->rs_more = true;
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&bf->list);
|
||||
if (!bf->bf_mpdu)
|
||||
|
@ -985,22 +992,22 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_hdr *hdr;
|
||||
bool discard_current = sc->rx.discard_next;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Discard corrupt descriptors which are marked in
|
||||
* ath_get_next_rx_buf().
|
||||
*/
|
||||
sc->rx.discard_next = rx_stats->rs_more;
|
||||
if (discard_current)
|
||||
return -EINVAL;
|
||||
goto corrupt;
|
||||
|
||||
sc->rx.discard_next = false;
|
||||
|
||||
/*
|
||||
* Discard zero-length packets.
|
||||
*/
|
||||
if (!rx_stats->rs_datalen) {
|
||||
RX_STAT_INC(rx_len_err);
|
||||
return -EINVAL;
|
||||
goto corrupt;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1010,7 +1017,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
*/
|
||||
if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
|
||||
RX_STAT_INC(rx_len_err);
|
||||
return -EINVAL;
|
||||
goto corrupt;
|
||||
}
|
||||
|
||||
/* Only use status info from the last fragment */
|
||||
|
@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
* This is different from the other corrupt descriptor
|
||||
* condition handled above.
|
||||
*/
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
|
||||
goto corrupt;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
|
||||
|
||||
|
@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
|
||||
RX_STAT_INC(rx_spectral);
|
||||
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* everything but the rate is checked here, the rate check is done
|
||||
* separately to avoid doing two lookups for a rate for each frame.
|
||||
*/
|
||||
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
|
||||
return -EINVAL;
|
||||
|
||||
if (ath_is_mybeacon(common, hdr)) {
|
||||
RX_STAT_INC(rx_beacons);
|
||||
|
@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
/*
|
||||
* This shouldn't happen, but have a safety check anyway.
|
||||
*/
|
||||
if (WARN_ON(!ah->curchan)) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (WARN_ON(!ah->curchan))
|
||||
return -EINVAL;
|
||||
|
||||
if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
|
||||
ret =-EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
|
||||
return -EINVAL;
|
||||
|
||||
ath9k_process_rssi(common, hw, rx_stats, rx_status);
|
||||
|
||||
|
@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
sc->rx.num_pkts++;
|
||||
#endif
|
||||
|
||||
exit:
|
||||
sc->rx.discard_next = false;
|
||||
return ret;
|
||||
return 0;
|
||||
|
||||
corrupt:
|
||||
sc->rx.discard_next = rx_stats->rs_more;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
||||
|
|
|
@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
|
|||
for (tidno = 0, tid = &an->tid[tidno];
|
||||
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
|
||||
if (!tid->sched)
|
||||
continue;
|
||||
|
||||
ac = tid->ac;
|
||||
txq = ac->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
if (!tid->sched) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
continue;
|
||||
}
|
||||
|
||||
buffered = ath_tid_has_buffered(tid);
|
||||
|
||||
tid->sched = false;
|
||||
|
@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
txq->stopped = true;
|
||||
}
|
||||
|
||||
if (txctl->an)
|
||||
tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
txq = sc->tx.uapsdq;
|
||||
ath_txq_lock(sc, txq);
|
||||
} else if (txctl->an &&
|
||||
ieee80211_is_data_present(hdr->frame_control)) {
|
||||
tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||
|
||||
WARN_ON(tid->ac->txq != txctl->txq);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
|
||||
|
|
|
@ -457,7 +457,6 @@ struct brcmf_sdio {
|
|||
|
||||
u8 tx_hdrlen; /* sdio bus header length for tx packet */
|
||||
bool txglom; /* host tx glomming enable flag */
|
||||
struct sk_buff *txglom_sgpad; /* scatter-gather padding buffer */
|
||||
u16 head_align; /* buffer pointer alignment */
|
||||
u16 sgentry_align; /* scatter-gather buffer alignment */
|
||||
};
|
||||
|
@ -1944,9 +1943,8 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
|
|||
if (lastfrm && chain_pad)
|
||||
tail_pad += blksize - chain_pad;
|
||||
if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
|
||||
pkt_pad = bus->txglom_sgpad;
|
||||
if (pkt_pad == NULL)
|
||||
brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
|
||||
pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop +
|
||||
bus->head_align);
|
||||
if (pkt_pad == NULL)
|
||||
return -ENOMEM;
|
||||
ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad);
|
||||
|
@ -1957,6 +1955,7 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
|
|||
tail_chop);
|
||||
*(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
|
||||
skb_trim(pkt, pkt->len - tail_chop);
|
||||
skb_trim(pkt_pad, tail_pad + tail_chop);
|
||||
__skb_queue_after(pktq, pkt, pkt_pad);
|
||||
} else {
|
||||
ntail = pkt->data_len + tail_pad -
|
||||
|
@ -2011,7 +2010,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
|
|||
return ret;
|
||||
head_pad = (u16)ret;
|
||||
if (head_pad)
|
||||
memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen);
|
||||
memset(pkt_next->data + bus->tx_hdrlen, 0, head_pad);
|
||||
|
||||
total_len += pkt_next->len;
|
||||
|
||||
|
@ -3486,10 +3485,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
|
|||
bus->txglom = false;
|
||||
value = 1;
|
||||
pad_size = bus->sdiodev->func[2]->cur_blksize << 1;
|
||||
bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size);
|
||||
if (!bus->txglom_sgpad)
|
||||
brcmf_err("allocating txglom padding skb failed, reduced performance\n");
|
||||
|
||||
err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
|
||||
&value, sizeof(u32));
|
||||
if (err < 0) {
|
||||
|
@ -4053,7 +4048,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
|
|||
brcmf_sdio_chip_detach(&bus->ci);
|
||||
}
|
||||
|
||||
brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
|
||||
kfree(bus->rxbuf);
|
||||
kfree(bus->hdrbuf);
|
||||
kfree(bus);
|
||||
|
|
|
@ -147,7 +147,7 @@ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
|
|||
|
||||
if (!sta->ap && sta->u.sta.challenge)
|
||||
kfree(sta->u.sta.challenge);
|
||||
del_timer(&sta->timer);
|
||||
del_timer_sync(&sta->timer);
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
|
||||
kfree(sta);
|
||||
|
|
|
@ -590,6 +590,7 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
|
|||
sizeof(priv->tid_data[sta_id][tid]));
|
||||
|
||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
|
||||
priv->num_stations--;
|
||||
|
||||
|
|
|
@ -621,7 +621,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
|
|||
id = *pos++;
|
||||
elen = *pos++;
|
||||
left -= 2;
|
||||
if (elen > left || elen == 0) {
|
||||
if (elen > left) {
|
||||
lbs_deb_scan("scan response: invalid IE fmt\n");
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -1211,6 +1211,12 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
|
|||
rd_index = card->rxbd_rdptr & reg->rx_mask;
|
||||
skb_data = card->rx_buf_list[rd_index];
|
||||
|
||||
/* If skb allocation was failed earlier for Rx packet,
|
||||
* rx_buf_list[rd_index] would have been left with a NULL.
|
||||
*/
|
||||
if (!skb_data)
|
||||
return -ENOMEM;
|
||||
|
||||
MWIFIEX_SKB_PACB(skb_data, &buf_pa);
|
||||
pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
@ -1525,6 +1531,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
|
|||
if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
|
||||
mwifiex_process_sleep_confirm_resp(adapter, skb->data,
|
||||
skb->len);
|
||||
mwifiex_pcie_enable_host_int(adapter);
|
||||
if (mwifiex_write_reg(adapter,
|
||||
PCIE_CPU_INT_EVENT,
|
||||
CPU_INTR_SLEEP_CFM_DONE)) {
|
||||
dev_warn(adapter->dev,
|
||||
"Write register failed\n");
|
||||
return -1;
|
||||
}
|
||||
while (reg->sleep_cookie && (count++ < 10) &&
|
||||
mwifiex_pcie_ok_to_access_hw(adapter))
|
||||
usleep_range(50, 60);
|
||||
|
@ -1993,21 +2007,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
|
|||
adapter->int_status |= pcie_ireg;
|
||||
spin_unlock_irqrestore(&adapter->int_lock, flags);
|
||||
|
||||
if (pcie_ireg & HOST_INTR_CMD_DONE) {
|
||||
if ((adapter->ps_state == PS_STATE_SLEEP_CFM) ||
|
||||
(adapter->ps_state == PS_STATE_SLEEP)) {
|
||||
mwifiex_pcie_enable_host_int(adapter);
|
||||
if (mwifiex_write_reg(adapter,
|
||||
PCIE_CPU_INT_EVENT,
|
||||
CPU_INTR_SLEEP_CFM_DONE)
|
||||
) {
|
||||
dev_warn(adapter->dev,
|
||||
"Write register failed\n");
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
} else if (!adapter->pps_uapsd_mode &&
|
||||
if (!adapter->pps_uapsd_mode &&
|
||||
adapter->ps_state == PS_STATE_SLEEP &&
|
||||
mwifiex_pcie_ok_to_access_hw(adapter)) {
|
||||
/* Potentially for PCIe we could get other
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#define USB_VERSION "1.0"
|
||||
|
||||
static const char usbdriver_name[] = "usb8xxx";
|
||||
|
||||
static struct mwifiex_if_ops usb_ops;
|
||||
static struct semaphore add_remove_card_sem;
|
||||
static struct usb_card_rec *usb_card;
|
||||
|
@ -567,7 +565,7 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
|
|||
}
|
||||
|
||||
static struct usb_driver mwifiex_usb_driver = {
|
||||
.name = usbdriver_name,
|
||||
.name = "mwifiex_usb",
|
||||
.probe = mwifiex_usb_probe,
|
||||
.disconnect = mwifiex_usb_disconnect,
|
||||
.id_table = mwifiex_usb_table,
|
||||
|
|
|
@ -559,7 +559,8 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
|
|||
mwifiex_wmm_delete_all_ralist(priv);
|
||||
memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
|
||||
|
||||
if (priv->adapter->if_ops.clean_pcie_ring)
|
||||
if (priv->adapter->if_ops.clean_pcie_ring &&
|
||||
!priv->adapter->surprise_removed)
|
||||
priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
|
||||
}
|
||||
|
|
|
@ -1692,14 +1692,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
|||
void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb);
|
||||
void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs,
|
||||
void (*fn)(void *data), void *data);
|
||||
static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
|
||||
}
|
||||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs);
|
||||
void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
|
|
|
@ -3753,6 +3753,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
|||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (WARN_ON(!chanctx_conf)) {
|
||||
rcu_read_unlock();
|
||||
sta_info_free(local, new_sta);
|
||||
return -EINVAL;
|
||||
}
|
||||
rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
|
||||
|
|
|
@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *sta)
|
|||
sta->sta.addr, sta->sta.aid);
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
/*
|
||||
* Clear the flag only if the other one is still set
|
||||
* so that the TX path won't start TX'ing new frames
|
||||
* directly ... In the case that the driver flag isn't
|
||||
* set ieee80211_sta_ps_deliver_wakeup() will clear it.
|
||||
*/
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
|
||||
sta->sta.addr, sta->sta.aid);
|
||||
return;
|
||||
|
|
|
@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void cleanup_single_sta(struct sta_info *sta)
|
||||
static void __cleanup_single_sta(struct sta_info *sta)
|
||||
{
|
||||
int ac, i;
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
|
@ -99,7 +99,8 @@ static void cleanup_single_sta(struct sta_info *sta)
|
|||
struct ieee80211_local *local = sdata->local;
|
||||
struct ps_data *ps;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
|
||||
test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
ps = &sdata->bss->ps;
|
||||
|
@ -109,6 +110,7 @@ static void cleanup_single_sta(struct sta_info *sta)
|
|||
return;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
sta_info_recalc_tim(sta);
|
||||
|
@ -139,7 +141,14 @@ static void cleanup_single_sta(struct sta_info *sta)
|
|||
ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
|
||||
kfree(tid_tx);
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_single_sta(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
__cleanup_single_sta(sta);
|
||||
sta_info_free(local, sta);
|
||||
}
|
||||
|
||||
|
@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
rcu_read_unlock();
|
||||
|
||||
spin_lock_init(&sta->lock);
|
||||
spin_lock_init(&sta->ps_lock);
|
||||
INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
|
||||
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
|
||||
mutex_init(&sta->ampdu_mlme.mtx);
|
||||
|
@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
/* notify driver */
|
||||
err = sta_info_insert_drv_state(local, sdata, sta);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
local->num_sta++;
|
||||
local->sta_generation++;
|
||||
smp_mb();
|
||||
|
||||
/* simplify things and don't accept BA sessions yet */
|
||||
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
||||
/* make the station visible */
|
||||
sta_info_hash_add(local, sta);
|
||||
|
||||
list_add_rcu(&sta->list, &local->sta_list);
|
||||
|
||||
/* notify driver */
|
||||
err = sta_info_insert_drv_state(local, sdata, sta);
|
||||
if (err)
|
||||
goto out_remove;
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_INSERTED);
|
||||
/* accept BA sessions now */
|
||||
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
||||
ieee80211_recalc_min_chandef(sdata);
|
||||
ieee80211_sta_debugfs_add(sta);
|
||||
|
@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
|||
mesh_accept_plinks_update(sdata);
|
||||
|
||||
return 0;
|
||||
out_remove:
|
||||
sta_info_hash_del(local, sta);
|
||||
list_del_rcu(&sta->list);
|
||||
local->num_sta--;
|
||||
synchronize_net();
|
||||
__cleanup_single_sta(sta);
|
||||
out_err:
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
rcu_read_lock();
|
||||
|
@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_find_sta);
|
||||
|
||||
static void clear_sta_ps_flags(void *_sta)
|
||||
/* powersave support code */
|
||||
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
{
|
||||
struct sta_info *sta = _sta;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff_head pending;
|
||||
int filtered = 0, buffered = 0, ac;
|
||||
unsigned long flags;
|
||||
struct ps_data *ps;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
|
@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta)
|
|||
else
|
||||
return;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
}
|
||||
|
||||
/* powersave support code */
|
||||
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff_head pending;
|
||||
int filtered = 0, buffered = 0, ac;
|
||||
unsigned long flags;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_SP);
|
||||
|
||||
BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
|
||||
|
@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
|||
|
||||
skb_queue_head_init(&pending);
|
||||
|
||||
/* sync with ieee80211_tx_h_unicast_ps_buf */
|
||||
spin_lock(&sta->ps_lock);
|
||||
/* Send all buffered frames to the station */
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
int count = skb_queue_len(&pending), tmp;
|
||||
|
@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
|||
buffered += tmp - count;
|
||||
}
|
||||
|
||||
ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
|
||||
ieee80211_add_pending_skbs(local, &pending);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
spin_unlock(&sta->ps_lock);
|
||||
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
|
||||
/* This station just woke up and isn't aware of our SMPS state */
|
||||
if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
|
||||
|
|
|
@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat {
|
|||
* @drv_unblock_wk: used for driver PS unblocking
|
||||
* @listen_interval: listen interval of this station, when we're acting as AP
|
||||
* @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
|
||||
* @ps_lock: used for powersave (when mac80211 is the AP) related locking
|
||||
* @ps_tx_buf: buffers (per AC) of frames to transmit to this station
|
||||
* when it leaves power saving state or polls
|
||||
* @tx_filtered: buffers (per AC) of frames we already tried to
|
||||
|
@ -356,10 +357,8 @@ struct sta_info {
|
|||
/* use the accessors defined below */
|
||||
unsigned long _flags;
|
||||
|
||||
/*
|
||||
* STA powersave frame queues, no more than the internal
|
||||
* locking required.
|
||||
*/
|
||||
/* STA powersave lock and frame queues */
|
||||
spinlock_t ps_lock;
|
||||
struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
|
||||
struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
|
||||
unsigned long driver_buffered_tids;
|
||||
|
|
|
@ -478,6 +478,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
|||
sta->sta.addr, sta->sta.aid, ac);
|
||||
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
|
||||
purge_old_ps_buffers(tx->local);
|
||||
|
||||
/* sync with ieee80211_sta_ps_deliver_wakeup */
|
||||
spin_lock(&sta->ps_lock);
|
||||
/*
|
||||
* STA woke up the meantime and all the frames on ps_tx_buf have
|
||||
* been queued to pending queue. No reordering can happen, go
|
||||
* ahead and Tx the packet.
|
||||
*/
|
||||
if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
|
||||
!test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
spin_unlock(&sta->ps_lock);
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
|
||||
struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
|
||||
ps_dbg(tx->sdata,
|
||||
|
@ -492,6 +506,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
|||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
|
||||
spin_unlock(&sta->ps_lock);
|
||||
|
||||
if (!timer_pending(&local->sta_cleanup))
|
||||
mod_timer(&local->sta_cleanup,
|
||||
|
|
|
@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
|||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
}
|
||||
|
||||
void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs,
|
||||
void (*fn)(void *data), void *data)
|
||||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct sk_buff *skb;
|
||||
|
@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
|||
__skb_queue_tail(&local->pending[queue], skb);
|
||||
}
|
||||
|
||||
if (fn)
|
||||
fn(data);
|
||||
|
||||
for (i = 0; i < hw->queues; i++)
|
||||
__ieee80211_wake_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
|
@ -1740,6 +1736,26 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
|
||||
/*
|
||||
* Reconfigure sched scan if it was interrupted by FW restart or
|
||||
* suspend.
|
||||
*/
|
||||
mutex_lock(&local->mtx);
|
||||
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
|
||||
lockdep_is_held(&local->mtx));
|
||||
if (sched_scan_sdata && local->sched_scan_req)
|
||||
/*
|
||||
* Sched scan stopped, but we don't want to report it. Instead,
|
||||
* we're trying to reschedule.
|
||||
*/
|
||||
if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
|
||||
local->sched_scan_req))
|
||||
sched_scan_stopped = true;
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
if (sched_scan_stopped)
|
||||
cfg80211_sched_scan_stopped(local->hw.wiphy);
|
||||
|
||||
/*
|
||||
* If this is for hw restart things are still running.
|
||||
* We may want to change that later, however.
|
||||
|
@ -1768,26 +1784,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
WARN_ON(1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reconfigure sched scan if it was interrupted by FW restart or
|
||||
* suspend.
|
||||
*/
|
||||
mutex_lock(&local->mtx);
|
||||
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
|
||||
lockdep_is_held(&local->mtx));
|
||||
if (sched_scan_sdata && local->sched_scan_req)
|
||||
/*
|
||||
* Sched scan stopped, but we don't want to report it. Instead,
|
||||
* we're trying to reschedule.
|
||||
*/
|
||||
if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
|
||||
local->sched_scan_req))
|
||||
sched_scan_stopped = true;
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
if (sched_scan_stopped)
|
||||
cfg80211_sched_scan_stopped(local->hw.wiphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
|||
return IEEE80211_AC_BE;
|
||||
}
|
||||
|
||||
if (skb->protocol == sdata->control_port_protocol) {
|
||||
skb->priority = 7;
|
||||
return ieee80211_downgrade_queue(sdata, skb);
|
||||
}
|
||||
|
||||
/* use the data classifier to determine what 802.1d tag the
|
||||
* data frame has */
|
||||
rcu_read_lock();
|
||||
|
|
|
@ -301,7 +301,7 @@ static int nci_open_device(struct nci_dev *ndev)
|
|||
rc = __nci_request(ndev, nci_reset_req, 0,
|
||||
msecs_to_jiffies(NCI_RESET_TIMEOUT));
|
||||
|
||||
if (ndev->ops->setup(ndev))
|
||||
if (ndev->ops->setup)
|
||||
ndev->ops->setup(ndev);
|
||||
|
||||
if (!rc) {
|
||||
|
|
|
@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
|||
return;
|
||||
case NL80211_REGDOM_SET_BY_USER:
|
||||
treatment = reg_process_hint_user(reg_request);
|
||||
if (treatment == REG_REQ_OK ||
|
||||
if (treatment == REG_REQ_IGNORE ||
|
||||
treatment == REG_REQ_ALREADY_SET)
|
||||
return;
|
||||
schedule_delayed_work(®_timeout, msecs_to_jiffies(3142));
|
||||
|
|
Loading…
Reference in New Issue
Block a user