Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/wireless/mediatek/mt76/mt7603/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  dma.c   Sprache: C

 
// SPDX-License-Identifier: ISC

#include "mt7603.h"
#include "mac.h"
#include "../dma.h"

static const u8 wmm_queue_map[] = {
 [IEEE80211_AC_BK] = 0,
 [IEEE80211_AC_BE] = 1,
 [IEEE80211_AC_VI] = 2,
 [IEEE80211_AC_VO] = 3,
};

static void
mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
{
 static const u8 tid_to_ac[8] = {
  IEEE80211_AC_BE,
  IEEE80211_AC_BK,
  IEEE80211_AC_BK,
  IEEE80211_AC_BE,
  IEEE80211_AC_VI,
  IEEE80211_AC_VI,
  IEEE80211_AC_VO,
  IEEE80211_AC_VO
 };
 __le32 *txd = (__le32 *)skb->data;
 struct ieee80211_hdr *hdr;
 struct ieee80211_sta *sta;
 struct mt7603_sta *msta;
 struct mt76_wcid *wcid;
 u8 qid, tid = 0, hwq = 0;
 void *priv;
 int idx;
 u32 val;

 if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr))
  goto free;

 val = le32_to_cpu(txd[1]);
 idx = FIELD_GET(MT_TXD1_WLAN_IDX, val);
 skb->priority = FIELD_GET(MT_TXD1_TID, val);

 if (idx >= MT7603_WTBL_STA - 1)
  goto free;

 wcid = mt76_wcid_ptr(dev, idx);
 if (!wcid)
  goto free;

 priv = msta = container_of(wcid, struct mt7603_sta, wcid);

 sta = container_of(priv, struct ieee80211_sta, drv_priv);
 hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE];

 hwq = wmm_queue_map[IEEE80211_AC_BE];
 if (ieee80211_is_data_qos(hdr->frame_control)) {
  tid = *ieee80211_get_qos_ctl(hdr) &
    IEEE80211_QOS_CTL_TAG1D_MASK;
  qid = tid_to_ac[tid];
  hwq = wmm_queue_map[qid];
  skb_set_queue_mapping(skb, qid);
 } else if (ieee80211_is_data(hdr->frame_control)) {
  skb_set_queue_mapping(skb, IEEE80211_AC_BE);
  hwq = wmm_queue_map[IEEE80211_AC_BE];
 } else {
  skb_pull(skb, MT_TXD_SIZE);
  if (!ieee80211_is_bufferable_mmpdu(skb))
   goto free;
  skb_push(skb, MT_TXD_SIZE);
  skb_set_queue_mapping(skb, MT_TXQ_PSD);
  hwq = MT_TX_HW_QUEUE_MGMT;
 }

 ieee80211_sta_set_buffered(sta, tid, true);

 val = le32_to_cpu(txd[0]);
 val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
 val |= FIELD_PREP(MT_TXD0_Q_IDX, hwq);
 txd[0] = cpu_to_le32(val);

 spin_lock_bh(&dev->ps_lock);
 __skb_queue_tail(&msta->psq, skb);
 if (skb_queue_len(&msta->psq) >= 64) {
  skb = __skb_dequeue(&msta->psq);
  dev_kfree_skb(skb);
 }
 spin_unlock_bh(&dev->ps_lock);
 return;

free:
 dev_kfree_skb(skb);
}

void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
    struct sk_buff *skb, u32 *info)
{
 struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
 __le32 *rxd = (__le32 *)skb->data;
 __le32 *end = (__le32 *)&skb->data[skb->len];
 enum rx_pkt_type type;

 type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);

 if (q == MT_RXQ_MCU) {
  if (type == PKT_TYPE_RX_EVENT)
   mt76_mcu_rx_event(&dev->mt76, skb);
  else
   mt7603_rx_loopback_skb(dev, skb);
  return;
 }

 switch (type) {
 case PKT_TYPE_TXS:
  for (rxd++; rxd + 5 <= end; rxd += 5)
   mt7603_mac_add_txs(dev, rxd);
  dev_kfree_skb(skb);
  break;
 case PKT_TYPE_RX_EVENT:
  mt76_mcu_rx_event(&dev->mt76, skb);
  return;
 case PKT_TYPE_NORMAL:
  if (mt7603_mac_fill_rx(dev, skb) == 0) {
   mt76_rx(&dev->mt76, q, skb);
   return;
  }
  fallthrough;
 default:
  dev_kfree_skb(skb);
  break;
 }
}

static int
mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q,
       int idx, int n_desc, int bufsize)
{
 int err;

 err = mt76_queue_alloc(dev, q, idx, n_desc, bufsize,
          MT_RX_RING_BASE);
 if (err < 0)
  return err;

 mt7603_irq_enable(dev, MT_INT_RX_DONE(idx));

 return 0;
}

static int mt7603_poll_tx(struct napi_struct *napi, int budget)
{
 struct mt7603_dev *dev;
 int i;

 dev = container_of(napi, struct mt7603_dev, mt76.tx_napi);
 dev->tx_dma_check = 0;

 mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
 for (i = MT_TXQ_PSD; i >= 0; i--)
  mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);

 if (napi_complete_done(napi, 0))
  mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL);

 mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
 for (i = MT_TXQ_PSD; i >= 0; i--)
  mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);

 mt7603_mac_sta_poll(dev);

 mt76_worker_schedule(&dev->mt76.tx_worker);

 return 0;
}

int mt7603_dma_init(struct mt7603_dev *dev)
{
 int ret;
 int i;

 mt76_dma_attach(&dev->mt76);

 mt76_clear(dev, MT_WPDMA_GLO_CFG,
     MT_WPDMA_GLO_CFG_TX_DMA_EN |
     MT_WPDMA_GLO_CFG_RX_DMA_EN |
     MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
     MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);

 mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
 mt7603_pse_client_reset(dev);

 for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
  ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
      MT7603_TX_RING_SIZE, MT_TX_RING_BASE,
      NULL, 0);
  if (ret)
   return ret;
 }

 ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
     MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, NULL, 0);
 if (ret)
  return ret;

 ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT_TX_HW_QUEUE_MCU,
      MT_MCU_RING_SIZE, MT_TX_RING_BASE);
 if (ret)
  return ret;

 ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN,
     MT_MCU_RING_SIZE, MT_TX_RING_BASE, NULL, 0);
 if (ret)
  return ret;

 ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC,
     MT_MCU_RING_SIZE, MT_TX_RING_BASE, NULL, 0);
 if (ret)
  return ret;

 mt7603_irq_enable(dev,
     MT_INT_TX_DONE(IEEE80211_AC_VO) |
     MT_INT_TX_DONE(IEEE80211_AC_VI) |
     MT_INT_TX_DONE(IEEE80211_AC_BE) |
     MT_INT_TX_DONE(IEEE80211_AC_BK) |
     MT_INT_TX_DONE(MT_TX_HW_QUEUE_MGMT) |
     MT_INT_TX_DONE(MT_TX_HW_QUEUE_MCU) |
     MT_INT_TX_DONE(MT_TX_HW_QUEUE_BCN) |
     MT_INT_TX_DONE(MT_TX_HW_QUEUE_BMC));

 ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
       MT7603_MCU_RX_RING_SIZE, MT_RX_BUF_SIZE);
 if (ret)
  return ret;

 ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
       MT7603_RX_RING_SIZE, MT_RX_BUF_SIZE);
 if (ret)
  return ret;

 mt76_wr(dev, MT_DELAY_INT_CFG, 0);
 ret = mt76_init_queues(dev, mt76_dma_rx_poll);
 if (ret)
  return ret;

 netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
     mt7603_poll_tx);
 napi_enable(&dev->mt76.tx_napi);

 return 0;
}

void mt7603_dma_cleanup(struct mt7603_dev *dev)
{
 mt76_clear(dev, MT_WPDMA_GLO_CFG,
     MT_WPDMA_GLO_CFG_TX_DMA_EN |
     MT_WPDMA_GLO_CFG_RX_DMA_EN |
     MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);

 mt76_dma_cleanup(&dev->mt76);
}

Messung V0.5
C=98 H=92 G=94

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.