]> Git Repo - J-linux.git/commitdiff
Kalle Valo says:
authorJakub Kicinski <[email protected]>
Sat, 29 Oct 2022 01:31:39 +0000 (18:31 -0700)
committerJakub Kicinski <[email protected]>
Sat, 29 Oct 2022 01:31:40 +0000 (18:31 -0700)
====================
pull-request: wireless-next-2022-10-28

First set of patches v6.2. mac80211 refactoring continues for Wi-Fi 7.
All mac80211 driver are now converted to use internal TX queues, this
might cause some regressions so we wanted to do this early in the
cycle.

Note: wireless tree was merged[1] to wireless-next to avoid some
conflicts with mac80211 patches between the trees. Unfortunately there
are still two smaller conflicts in net/mac80211/util.c which Stephen
also reported[2]. In the first conflict initialise scratch_len to
"params->scratch_len ?: 3 * params->len" (note number 3, not 2!) and
in the second conflict take the version which uses elems->scratch_pos.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=dfd2d876b3fda1790bc0239ba4c6967e25d16e91
[2] https://lore.kernel.org/all/20221020032340.5cf101c0@canb.auug.org.au/

mac80211
 - preparation for Wi-Fi 7 Multi-Link Operation (MLO) continues
 - add API to show the link STAs in debugfs
 - all mac80211 drivers are now using mac80211 internal TX queues (iTXQs)

rtw89
 - support 8852BE

rtl8xxxu
 - support RTL8188FU

brmfmac
 - support two station interfaces concurrently

bcma
 - support SPROM rev 11
====================

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
1  2 
drivers/bcma/driver_gpio.c
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/ti/wlcore/main.c
drivers/staging/vt6655/device_main.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/util.c

index 65fb9bad1577aaea2065e96bd6d78edefb9a1689,eff6fc330632376f67203f3b1d29c4661cf5bcf3..5f90bac6bb09e97c8ab1642f2747d34ae37f855e
@@@ -82,6 -82,7 +82,7 @@@ static void bcma_gpio_irq_unmask(struc
        int gpio = irqd_to_hwirq(d);
        u32 val = bcma_chipco_gpio_in(cc, BIT(gpio));
  
+       gpiochip_enable_irq(gc, gpio);
        bcma_chipco_gpio_polarity(cc, BIT(gpio), val);
        bcma_chipco_gpio_intmask(cc, BIT(gpio), BIT(gpio));
  }
@@@ -93,12 -94,15 +94,15 @@@ static void bcma_gpio_irq_mask(struct i
        int gpio = irqd_to_hwirq(d);
  
        bcma_chipco_gpio_intmask(cc, BIT(gpio), 0);
+       gpiochip_disable_irq(gc, gpio);
  }
  
- static struct irq_chip bcma_gpio_irq_chip = {
+ static const struct irq_chip bcma_gpio_irq_chip = {
        .name           = "BCMA-GPIO",
        .irq_mask       = bcma_gpio_irq_mask,
        .irq_unmask     = bcma_gpio_irq_unmask,
+       .flags          = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };
  
  static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id)
                return IRQ_NONE;
  
        for_each_set_bit(gpio, &irqs, gc->ngpio)
 -              generic_handle_irq(irq_find_mapping(gc->irq.domain, gpio));
 +              generic_handle_domain_irq_safe(gc->irq.domain, gpio);
        bcma_chipco_gpio_polarity(cc, irqs, val & irqs);
  
        return IRQ_HANDLED;
@@@ -139,7 -143,7 +143,7 @@@ static int bcma_gpio_irq_init(struct bc
        bcma_chipco_gpio_intmask(cc, ~0, 0);
        bcma_cc_set32(cc, BCMA_CC_IRQMASK, BCMA_CC_IRQ_GPIO);
  
-       girq->chip = &bcma_gpio_irq_chip;
+       gpio_irq_chip_set_chip(girq, &bcma_gpio_irq_chip);
        /* This will let us handle the parent IRQ in the driver */
        girq->parent_handler = NULL;
        girq->num_parents = 0;
index 2d1e3fd9b526c16c190bcc02af249261e624aece,8094384b86164771045c29674c84c4d5488578eb..3cbcbb93a1a7a1c6556b15c794f51ad5ea056933
@@@ -2081,7 -2081,7 +2081,7 @@@ static void ath11k_peer_assoc_h_he(stru
        struct cfg80211_chan_def def;
        const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
        enum nl80211_band band;
 -      u16 *he_mcs_mask;
 +      u16 he_mcs_mask[NL80211_HE_NSS_MAX];
        u8 max_nss, he_mcs;
        u16 he_tx_mcs = 0, v = 0;
        int i, he_nss, nss_idx;
                return;
  
        band = def.chan->band;
 -      he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs;
 +      memcpy(he_mcs_mask, arvif->bitrate_mask.control[band].he_mcs,
 +             sizeof(he_mcs_mask));
  
        if (ath11k_peer_assoc_h_he_masked(he_mcs_mask))
                return;
@@@ -8539,6 -8538,7 +8539,7 @@@ err_fallback
  
  static const struct ieee80211_ops ath11k_ops = {
        .tx                             = ath11k_mac_op_tx,
+       .wake_tx_queue                  = ieee80211_handle_wake_tx_queue,
        .start                          = ath11k_mac_op_start,
        .stop                           = ath11k_mac_op_stop,
        .reconfig_complete              = ath11k_mac_op_reconfig_complete,
index a40636c90ec365975284bdc4ace553d97f22a857,19c7fa29ec781650fa89626489673cfff8f159c3..1927fc8111ffbdc56bd45d774b2cebef922d6ca9
@@@ -3104,6 -3104,7 +3104,7 @@@ static int mac80211_hwsim_change_sta_li
  
  #define HWSIM_COMMON_OPS                                      \
        .tx = mac80211_hwsim_tx,                                \
+       .wake_tx_queue = ieee80211_handle_wake_tx_queue,        \
        .start = mac80211_hwsim_start,                          \
        .stop = mac80211_hwsim_stop,                            \
        .add_interface = mac80211_hwsim_add_interface,          \
@@@ -4973,8 -4974,6 +4974,8 @@@ static int hwsim_cloned_frame_received_
        }
  
        rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
 +      if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates)
 +              goto out;
        rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
  
        hdr = (void *)skb->data;
index 28c0f06e311f75fb1739f0c81b6aa8aae978ef62,f1f1b3542b6c91a53f2823d8053e07e2cb3385b1..bf21611872a3c1ac81438a72439d694933083ef7
@@@ -5942,6 -5942,7 +5942,7 @@@ static const struct ieee80211_ops wl127
        .prepare_multicast = wl1271_op_prepare_multicast,
        .configure_filter = wl1271_op_configure_filter,
        .tx = wl1271_op_tx,
+       .wake_tx_queue = ieee80211_handle_wake_tx_queue,
        .set_key = wlcore_op_set_key,
        .hw_scan = wl1271_op_hw_scan,
        .cancel_hw_scan = wl1271_op_cancel_hw_scan,
@@@ -6100,7 -6101,7 +6101,7 @@@ static int wl1271_register_hw(struct wl
                        wl1271_warning("Fuse mac address is zero. using random mac");
                        /* Use TI oui and a random nic */
                        oui_addr = WLCORE_TI_OUI_ADDRESS;
 -                      nic_addr = get_random_int();
 +                      nic_addr = get_random_u32();
                } else {
                        oui_addr = wl->fuse_oui_addr;
                        /* fuse has the BD_ADDR, the WLAN addresses are the next two */
index 56c3cf3ba53d91e976e978a1324e846bdb12e70b,f6f5da4c55d17a6fcae0e43308425ef6cac6c374..45e5eccadb44143f4445a755605c04478e113c03
@@@ -205,55 -205,6 +205,55 @@@ static void vt6655_mac_read_ether_addr(
        iowrite8(0, iobase + MAC_REG_PAGE1SEL);
  }
  
 +static void vt6655_mac_dma_ctl(void __iomem *iobase, u8 reg_index)
 +{
 +      u32 reg_value;
 +
 +      reg_value = ioread32(iobase + reg_index);
 +      if (reg_value & DMACTL_RUN)
 +              iowrite32(DMACTL_WAKE, iobase + reg_index);
 +      else
 +              iowrite32(DMACTL_RUN, iobase + reg_index);
 +}
 +
 +static void vt6655_mac_set_bits(void __iomem *iobase, u32 mask)
 +{
 +      u32 reg_value;
 +
 +      reg_value = ioread32(iobase + MAC_REG_ENCFG);
 +      reg_value = reg_value | mask;
 +      iowrite32(reg_value, iobase + MAC_REG_ENCFG);
 +}
 +
 +static void vt6655_mac_clear_bits(void __iomem *iobase, u32 mask)
 +{
 +      u32 reg_value;
 +
 +      reg_value = ioread32(iobase + MAC_REG_ENCFG);
 +      reg_value = reg_value & ~mask;
 +      iowrite32(reg_value, iobase + MAC_REG_ENCFG);
 +}
 +
 +static void vt6655_mac_en_protect_md(void __iomem *iobase)
 +{
 +      vt6655_mac_set_bits(iobase, ENCFG_PROTECTMD);
 +}
 +
 +static void vt6655_mac_dis_protect_md(void __iomem *iobase)
 +{
 +      vt6655_mac_clear_bits(iobase, ENCFG_PROTECTMD);
 +}
 +
 +static void vt6655_mac_en_barker_preamble_md(void __iomem *iobase)
 +{
 +      vt6655_mac_set_bits(iobase, ENCFG_BARKERPREAM);
 +}
 +
 +static void vt6655_mac_dis_barker_preamble_md(void __iomem *iobase)
 +{
 +      vt6655_mac_clear_bits(iobase, ENCFG_BARKERPREAM);
 +}
 +
  /*
   * Initialisation of MAC & BBP registers
   */
@@@ -400,11 -351,11 +400,11 @@@ static void device_init_registers(struc
        }
  
        if (priv->local_id > REV_ID_VT3253_B1) {
 -              MACvSelectPage1(priv->port_offset);
 +              VT6655_MAC_SELECT_PAGE1(priv->port_offset);
  
                iowrite8(MSRCTL1_TXPWR | MSRCTL1_CSAPAREN, priv->port_offset + MAC_REG_MSRCTL + 1);
  
 -              MACvSelectPage0(priv->port_offset);
 +              VT6655_MAC_SELECT_PAGE0(priv->port_offset);
        }
  
        /* use relative tx timeout and 802.11i D4 */
                                    (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
  
        /* set performance parameter by registry */
 -      MACvSetShortRetryLimit(priv, priv->byShortRetryLimit);
 +      vt6655_mac_set_short_retry_limit(priv, priv->byShortRetryLimit);
        MACvSetLongRetryLimit(priv, priv->byLongRetryLimit);
  
        /* reset TSF counter */
                vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_RCR, RCR_WPAERR);
  
        /* Turn On Rx DMA */
 -      MACvReceive0(priv->port_offset);
 -      MACvReceive1(priv->port_offset);
 +      vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0);
 +      vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1);
  
        /* start the adapter */
        iowrite8(HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON, priv->port_offset + MAC_REG_HOSTCR);
@@@ -586,12 -537,13 +586,12 @@@ static void device_free_rings(struct vn
                          priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
                          priv->aRD0Ring, priv->pool_dma);
  
 -      if (priv->tx0_bufs)
 -              dma_free_coherent(&priv->pcid->dev,
 -                                priv->opts.tx_descs[0] * PKT_BUF_SZ +
 -                                priv->opts.tx_descs[1] * PKT_BUF_SZ +
 -                                CB_BEACON_BUF_SIZE +
 -                                CB_MAX_BUF_SIZE,
 -                                priv->tx0_bufs, priv->tx_bufs_dma0);
 +      dma_free_coherent(&priv->pcid->dev,
 +                        priv->opts.tx_descs[0] * PKT_BUF_SZ +
 +                        priv->opts.tx_descs[1] * PKT_BUF_SZ +
 +                        CB_BEACON_BUF_SIZE +
 +                        CB_MAX_BUF_SIZE,
 +                        priv->tx0_bufs, priv->tx_bufs_dma0);
  }
  
  static int device_init_rd0_ring(struct vnt_private *priv)
@@@ -631,7 -583,7 +631,7 @@@ err_free_rd
        kfree(desc->rd_info);
  
  err_free_desc:
 -      while (--i) {
 +      while (i--) {
                desc = &priv->aRD0Ring[i];
                device_free_rx_buf(priv, desc);
                kfree(desc->rd_info);
@@@ -677,7 -629,7 +677,7 @@@ err_free_rd
        kfree(desc->rd_info);
  
  err_free_desc:
 -      while (--i) {
 +      while (i--) {
                desc = &priv->aRD1Ring[i];
                device_free_rx_buf(priv, desc);
                kfree(desc->rd_info);
@@@ -742,7 -694,7 +742,7 @@@ static int device_init_td0_ring(struct 
        return 0;
  
  err_free_desc:
 -      while (--i) {
 +      while (i--) {
                desc = &priv->apTD0Rings[i];
                kfree(desc->td_info);
        }
@@@ -782,7 -734,7 +782,7 @@@ static int device_init_td1_ring(struct 
        return 0;
  
  err_free_desc:
 -      while (--i) {
 +      while (i--) {
                desc = &priv->apTD1Rings[i];
                kfree(desc->td_info);
        }
@@@ -1183,8 -1135,8 +1183,8 @@@ static void vnt_interrupt_process(struc
  
                isr = ioread32(priv->port_offset + MAC_REG_ISR);
  
 -              MACvReceive0(priv->port_offset);
 -              MACvReceive1(priv->port_offset);
 +              vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0);
 +              vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1);
  
                if (max_count > priv->opts.int_works)
                        break;
@@@ -1266,9 -1218,9 +1266,9 @@@ static int vnt_tx_packet(struct vnt_pri
        wmb(); /* second memory barrier */
  
        if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB)
 -              MACvTransmitAC0(priv->port_offset);
 +              vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_AC0DMACTL);
        else
 -              MACvTransmit0(priv->port_offset);
 +              vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_TXDMACTL0);
  
        priv->iTDUsed[dma_idx]++;
  
@@@ -1488,19 -1440,19 +1488,19 @@@ static void vnt_bss_info_changed(struc
  
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
                if (conf->use_short_preamble) {
 -                      MACvEnableBarkerPreambleMd(priv->port_offset);
 +                      vt6655_mac_en_barker_preamble_md(priv->port_offset);
                        priv->preamble_type = true;
                } else {
 -                      MACvDisableBarkerPreambleMd(priv->port_offset);
 +                      vt6655_mac_dis_barker_preamble_md(priv->port_offset);
                        priv->preamble_type = false;
                }
        }
  
        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
                if (conf->use_cts_prot)
 -                      MACvEnableProtectMD(priv->port_offset);
 +                      vt6655_mac_en_protect_md(priv->port_offset);
                else
 -                      MACvDisableProtectMD(priv->port_offset);
 +                      vt6655_mac_dis_protect_md(priv->port_offset);
        }
  
        if (changed & BSS_CHANGED_ERP_SLOT) {
@@@ -1586,21 -1538,21 +1586,21 @@@ static void vnt_configure(struct ieee80
                        spin_lock_irqsave(&priv->lock, flags);
  
                        if (priv->mc_list_count > 2) {
 -                              MACvSelectPage1(priv->port_offset);
 +                              VT6655_MAC_SELECT_PAGE1(priv->port_offset);
  
                                iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0);
                                iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0 + 4);
  
 -                              MACvSelectPage0(priv->port_offset);
 +                              VT6655_MAC_SELECT_PAGE0(priv->port_offset);
                        } else {
 -                              MACvSelectPage1(priv->port_offset);
 +                              VT6655_MAC_SELECT_PAGE1(priv->port_offset);
  
                                multicast =  le64_to_cpu(multicast);
                                iowrite32((u32)multicast, priv->port_offset +  MAC_REG_MAR0);
                                iowrite32((u32)(multicast >> 32),
                                          priv->port_offset + MAC_REG_MAR0 + 4);
  
 -                              MACvSelectPage0(priv->port_offset);
 +                              VT6655_MAC_SELECT_PAGE0(priv->port_offset);
                        }
  
                        spin_unlock_irqrestore(&priv->lock, flags);
@@@ -1685,6 -1637,7 +1685,7 @@@ static void vnt_reset_tsf(struct ieee80
  
  static const struct ieee80211_ops vnt_mac_ops = {
        .tx                     = vnt_tx_80211,
+       .wake_tx_queue          = ieee80211_handle_wake_tx_queue,
        .start                  = vnt_start,
        .stop                   = vnt_stop,
        .add_interface          = vnt_add_interface,
index 3d91b98db0996a2e1ec6d57fb035fc2988a94b09,f936d6b3f09320c9e4bdf069e1f3316b02af06dd..762346598338d34eba9736a6affab2abece685aa
@@@ -1963,9 -1963,6 +1963,6 @@@ minstrel_ht_alloc(struct ieee80211_hw *
                /* safe default, does not necessarily have to match hw properties */
                mp->max_retry = 7;
  
-       if (hw->max_rates >= 4)
-               mp->has_mrr = true;
        mp->hw = hw;
        mp->update_interval = HZ / 20;
  
@@@ -2036,7 -2033,7 +2033,7 @@@ static void __init init_sample_table(vo
  
        memset(sample_table, 0xff, sizeof(sample_table));
        for (col = 0; col < SAMPLE_COLUMNS; col++) {
 -              prandom_bytes(rnd, sizeof(rnd));
 +              get_random_bytes(rnd, sizeof(rnd));
                for (i = 0; i < MCS_GROUP_RATES; i++) {
                        new_idx = (i + rnd[i]) % MCS_GROUP_RATES;
                        while (sample_table[col][new_idx] != 0xff)
diff --combined net/mac80211/rx.c
index f99416d2e14417d4a667309d57dd2df1caa6084b,ac86910269034f1165562adda181dcf884460830..c28c6fbf786ee0cf9c5b4b6a99acb0cb514da989
@@@ -1571,9 -1571,6 +1571,6 @@@ static void sta_ps_start(struct sta_inf
  
        ieee80211_clear_fast_xmit(sta);
  
-       if (!sta->sta.txq[0])
-               return;
        for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
                struct ieee80211_txq *txq = sta->sta.txq[tid];
                struct txq_info *txqi = to_txq_info(txq);
@@@ -1978,11 -1975,10 +1975,11 @@@ ieee80211_rx_h_decrypt(struct ieee80211
  
                if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS ||
                    mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
 -                  NUM_DEFAULT_BEACON_KEYS) {
 -                      cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
 -                                                   skb->data,
 -                                                   skb->len);
 +                                 NUM_DEFAULT_BEACON_KEYS) {
 +                      if (rx->sdata->dev)
 +                              cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
 +                                                           skb->data,
 +                                                           skb->len);
                        return RX_DROP_MONITOR; /* unexpected BIP keyidx */
                }
  
        /* either the frame has been decrypted or will be dropped */
        status->flag |= RX_FLAG_DECRYPTED;
  
 -      if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE))
 +      if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE &&
 +                   rx->sdata->dev))
                cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
                                             skb->data, skb->len);
  
diff --combined net/mac80211/util.c
index b512cb37aafb77134b039218cf13520a5dbaa017,53217dc3f932b30c245794226c79d3c534e632dd..6f5407038459d03cc3ceaa4ac29a66c3da570a57
@@@ -288,6 -288,52 +288,52 @@@ __le16 ieee80211_ctstoself_duration(str
  }
  EXPORT_SYMBOL(ieee80211_ctstoself_duration);
  
+ static void wake_tx_push_queue(struct ieee80211_local *local,
+                              struct ieee80211_sub_if_data *sdata,
+                              struct ieee80211_txq *queue)
+ {
+       int q = sdata->vif.hw_queue[queue->ac];
+       struct ieee80211_tx_control control = {
+               .sta = queue->sta,
+       };
+       struct sk_buff *skb;
+       unsigned long flags;
+       bool q_stopped;
+       while (1) {
+               spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+               q_stopped = local->queue_stop_reasons[q];
+               spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+               if (q_stopped)
+                       break;
+               skb = ieee80211_tx_dequeue(&local->hw, queue);
+               if (!skb)
+                       break;
+               drv_tx(local, &control, skb);
+       }
+ }
+ /* wake_tx_queue handler for driver not implementing a custom one*/
+ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
+                                   struct ieee80211_txq *txq)
+ {
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
+       struct ieee80211_txq *queue;
+       /* Use ieee80211_next_txq() for airtime fairness accounting */
+       ieee80211_txq_schedule_start(hw, txq->ac);
+       while ((queue = ieee80211_next_txq(hw, txq->ac))) {
+               wake_tx_push_queue(local, sdata, queue);
+               ieee80211_return_txq(hw, queue, false);
+       }
+       ieee80211_txq_schedule_end(hw, txq->ac);
+ }
+ EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
  static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
  {
        struct ieee80211_local *local = sdata->local;
@@@ -400,39 -446,6 +446,6 @@@ void ieee80211_wake_txqs(struct tasklet
        spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
  }
  
- void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
- {
-       struct ieee80211_sub_if_data *sdata;
-       int n_acs = IEEE80211_NUM_ACS;
-       if (local->ops->wake_tx_queue)
-               return;
-       if (local->hw.queues < IEEE80211_NUM_ACS)
-               n_acs = 1;
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               int ac;
-               if (!sdata->dev)
-                       continue;
-               if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
-                   local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
-                       continue;
-               for (ac = 0; ac < n_acs; ac++) {
-                       int ac_queue = sdata->vif.hw_queue[ac];
-                       if (ac_queue == queue ||
-                           (sdata->vif.cab_queue == queue &&
-                            local->queue_stop_reasons[ac_queue] == 0 &&
-                            skb_queue_empty(&local->pending[ac_queue])))
-                               netif_wake_subqueue(sdata->dev, ac);
-               }
-       }
- }
  static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
                                   enum queue_stop_reason reason,
                                   bool refcounted,
                /* someone still has this queue stopped */
                return;
  
-       if (skb_queue_empty(&local->pending[queue])) {
-               rcu_read_lock();
-               ieee80211_propagate_queue_wake(local, queue);
-               rcu_read_unlock();
-       } else
+       if (!skb_queue_empty(&local->pending[queue]))
                tasklet_schedule(&local->tx_pending_tasklet);
  
        /*
         * release someone's lock, but it is fine because all the callers of
         * __ieee80211_wake_queue call it right before releasing the lock.
         */
-       if (local->ops->wake_tx_queue) {
-               if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
-                       tasklet_schedule(&local->wake_txqs_tasklet);
-               else
-                       _ieee80211_wake_txqs(local, flags);
-       }
+       if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
+               tasklet_schedule(&local->wake_txqs_tasklet);
+       else
+               _ieee80211_wake_txqs(local, flags);
  }
  
  void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
@@@ -539,10 -546,6 +546,6 @@@ static void __ieee80211_stop_queue(stru
                for (ac = 0; ac < n_acs; ac++) {
                        if (sdata->vif.hw_queue[ac] == queue ||
                            sdata->vif.cab_queue == queue) {
-                               if (!local->ops->wake_tx_queue) {
-                                       netif_stop_subqueue(sdata->dev, ac);
-                                       continue;
-                               }
                                spin_lock(&local->fq.lock);
                                sdata->vif.txqs_stopped[ac] = true;
                                spin_unlock(&local->fq.lock);
@@@ -1026,8 -1029,10 +1029,10 @@@ ieee80211_parse_extension_element(u32 *
                        elems->eht_operation = data;
                break;
        case WLAN_EID_EXT_EHT_MULTI_LINK:
-               if (ieee80211_mle_size_ok(data, len))
+               if (ieee80211_mle_size_ok(data, len)) {
                        elems->multi_link = (void *)data;
+                       elems->multi_link_len = len;
+               }
                break;
        }
  }
@@@ -1445,8 -1450,6 +1450,8 @@@ static size_t ieee802_11_find_bssid_pro
        for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
                if (elem->datalen < 2)
                        continue;
 +              if (elem->data[0] < 1 || elem->data[0] > 8)
 +                      continue;
  
                for_each_element(sub, elem->data + 1, elem->datalen - 1) {
                        u8 new_bssid[ETH_ALEN];
        return found ? profile_len : 0;
  }
  
+ static void ieee80211_defragment_element(struct ieee802_11_elems *elems,
+                                        void **elem_ptr, size_t *len,
+                                        size_t total_len, u8 frag_id)
+ {
+       u8 *data = *elem_ptr, *pos, *start;
+       const struct element *elem;
+       /*
+        * Since 'data' points to the data of the element, not the element
+        * itself, allow 254 in case it was an extended element where the
+        * extended ID isn't part of the data we see here and thus not part of
+        * 'len' either.
+        */
+       if (!data || (*len != 254 && *len != 255))
+               return;
+       start = elems->scratch_pos;
+       if (WARN_ON(*len > (elems->scratch + elems->scratch_len -
+                           elems->scratch_pos)))
+               return;
+       memcpy(elems->scratch_pos, data, *len);
+       elems->scratch_pos += *len;
+       pos = data + *len;
+       total_len -= *len;
+       for_each_element(elem, pos, total_len) {
+               if (elem->id != frag_id)
+                       break;
+               if (WARN_ON(elem->datalen >
+                           (elems->scratch + elems->scratch_len -
+                            elems->scratch_pos)))
+                       return;
+               memcpy(elems->scratch_pos, elem->data, elem->datalen);
+               elems->scratch_pos += elem->datalen;
+               *len += elem->datalen;
+       }
+       *elem_ptr = start;
+ }
+ static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems,
+                                      u8 link_id)
+ {
+       const struct ieee80211_multi_link_elem *ml = elems->multi_link;
+       size_t ml_len = elems->multi_link_len;
+       const struct element *sub;
+       if (!ml || !ml_len)
+               return;
+       if (le16_get_bits(ml->control, IEEE80211_ML_CONTROL_TYPE) !=
+           IEEE80211_ML_CONTROL_TYPE_BASIC)
+               return;
+       for_each_mle_subelement(sub, (u8 *)ml, ml_len) {
+               struct ieee80211_mle_per_sta_profile *prof = (void *)sub->data;
+               u16 control;
+               if (sub->id != IEEE80211_MLE_SUBELEM_PER_STA_PROFILE)
+                       continue;
+               if (!ieee80211_mle_sta_prof_size_ok(sub->data, sub->datalen))
+                       return;
+               control = le16_to_cpu(prof->control);
+               if (link_id != u16_get_bits(control,
+                                           IEEE80211_MLE_STA_CONTROL_LINK_ID))
+                       continue;
+               if (!(control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE))
+                       return;
+               elems->prof = prof;
+               elems->sta_prof_len = sub->datalen;
+               /* the sub element can be fragmented */
+               ieee80211_defragment_element(elems, (void **)&elems->prof,
+                                            &elems->sta_prof_len,
+                                            ml_len - (sub->data - (u8 *)ml),
+                                            IEEE80211_MLE_SUBELEM_FRAGMENT);
+               return;
+       }
+ }
+ static void ieee80211_mle_parse_link(struct ieee802_11_elems *elems,
+                                    struct ieee80211_elems_parse_params *params)
+ {
+       struct ieee80211_mle_per_sta_profile *prof;
+       struct ieee80211_elems_parse_params sub = {
+               .action = params->action,
+               .from_ap = params->from_ap,
+               .link_id = -1,
+       };
+       const struct element *non_inherit = NULL;
+       const u8 *end;
+       if (params->link_id == -1)
+               return;
+       ieee80211_defragment_element(elems, (void **)&elems->multi_link,
+                                    &elems->multi_link_len,
+                                    elems->total_len - ((u8 *)elems->multi_link -
+                                                        elems->ie_start),
+                                    WLAN_EID_FRAGMENT);
+       ieee80211_mle_get_sta_prof(elems, params->link_id);
+       prof = elems->prof;
+       if (!prof)
+               return;
+       /* check if we have the 4 bytes for the fixed part in assoc response */
+       if (elems->sta_prof_len < sizeof(*prof) + prof->sta_info_len - 1 + 4) {
+               elems->prof = NULL;
+               elems->sta_prof_len = 0;
+               return;
+       }
+       /*
+        * Skip the capability information and the status code that are expected
+        * as part of the station profile in association response frames. Note
+        * the -1 is because the 'sta_info_len' is accounted to as part of the
+        * per-STA profile, but not part of the 'u8 variable[]' portion.
+        */
+       sub.start = prof->variable + prof->sta_info_len - 1 + 4;
+       end = (const u8 *)prof + elems->sta_prof_len;
+       sub.len = end - sub.start;
+       non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
+                                            sub.start, sub.len);
+       _ieee802_11_parse_elems_full(&sub, elems, non_inherit);
+ }
  struct ieee802_11_elems *
  ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
  {
        const struct element *non_inherit = NULL;
        u8 *nontransmitted_profile;
        int nontransmitted_profile_len = 0;
-       size_t scratch_len = params->len;
 -      size_t scratch_len = params->scratch_len ?: 2 * params->len;
++      size_t scratch_len = params->scratch_len ?: 3 * params->len;
  
        elems = kzalloc(sizeof(*elems) + scratch_len, GFP_ATOMIC);
        if (!elems)
        elems->scratch_len = scratch_len;
        elems->scratch_pos = elems->scratch;
  
 -      nontransmitted_profile = kmalloc(params->len, GFP_ATOMIC);
 -      if (nontransmitted_profile) {
 -              nontransmitted_profile_len =
 -                      ieee802_11_find_bssid_profile(params->start, params->len,
 -                                                    elems, params->bss,
 -                                                    nontransmitted_profile);
 -              non_inherit =
 -                      cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
 -                                             nontransmitted_profile,
 -                                             nontransmitted_profile_len);
 -      }
 +      nontransmitted_profile = elems->scratch_pos;
 +      nontransmitted_profile_len =
 +              ieee802_11_find_bssid_profile(params->start, params->len,
 +                                            elems, params->bss,
 +                                            nontransmitted_profile);
 +      elems->scratch_pos += nontransmitted_profile_len;
 +      elems->scratch_len -= nontransmitted_profile_len;
 +      non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
 +                                           nontransmitted_profile,
 +                                           nontransmitted_profile_len);
  
        elems->crc = _ieee802_11_parse_elems_full(params, elems, non_inherit);
  
                _ieee802_11_parse_elems_full(&sub, elems, NULL);
        }
  
+       ieee80211_mle_parse_link(elems, params);
        if (elems->tim && !elems->parse_error) {
                const struct ieee80211_tim_ie *tim_ie = elems->tim;
  
            offsetofend(struct ieee80211_bssid_index, dtim_count))
                elems->dtim_count = elems->bssid_index->dtim_count;
  
 -      kfree(nontransmitted_profile);
 -
        return elems;
  }
  
This page took 0.18017 seconds and 4 git commands to generate.