mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
mt76x2: move rx queue processing to core
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -247,6 +247,78 @@ mt76_dma_init(struct mt76_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
|
||||
int len, bool more)
|
||||
{
|
||||
struct page *page = virt_to_head_page(data);
|
||||
int offset = data - page_address(page);
|
||||
struct sk_buff *skb = q->rx_head;
|
||||
|
||||
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, len,
|
||||
q->buf_size);
|
||||
|
||||
if (more)
|
||||
return;
|
||||
|
||||
q->rx_head = NULL;
|
||||
dev->drv->rx_skb(dev, q, skb);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned char *data;
|
||||
int len;
|
||||
int done = 0;
|
||||
bool napi = q == &dev->q_rx[MT_RXQ_MAIN];
|
||||
bool more;
|
||||
|
||||
while (done < budget) {
|
||||
u32 info;
|
||||
|
||||
data = mt76_dma_dequeue(dev, q, false, &len, &info, &more);
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
if (q->rx_head) {
|
||||
mt76_add_fragment(dev, q, data, len, more);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb = build_skb(data, q->buf_size);
|
||||
if (!skb) {
|
||||
skb_free_frag(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_reserve(skb, q->buf_offset);
|
||||
if (skb->tail + len > skb->end) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (q == &dev->q_rx[MT_RXQ_MCU]) {
|
||||
u32 * rxfce = (u32 *) skb->cb;
|
||||
*rxfce = info;
|
||||
}
|
||||
|
||||
__skb_put(skb, len);
|
||||
done++;
|
||||
|
||||
if (more) {
|
||||
q->rx_head = skb;
|
||||
continue;
|
||||
}
|
||||
|
||||
dev->drv->rx_skb(dev, q, skb);
|
||||
}
|
||||
|
||||
mt76_dma_rx_fill(dev, q, napi);
|
||||
return done;
|
||||
}
|
||||
|
||||
static const struct mt76_queue_ops mt76_dma_ops = {
|
||||
.init = mt76_dma_init,
|
||||
.alloc = mt76_dma_alloc_queue,
|
||||
@@ -255,6 +327,7 @@ static const struct mt76_queue_ops mt76_dma_ops = {
|
||||
.dequeue = mt76_dma_dequeue,
|
||||
.tx_cleanup = mt76_dma_tx_cleanup,
|
||||
.kick = mt76_dma_kick_queue,
|
||||
.rx_process = mt76_dma_rx_process,
|
||||
};
|
||||
|
||||
int mt76_dma_attach(struct mt76_dev *dev)
|
||||
|
||||
@@ -107,6 +107,8 @@ struct mt76_queue_ops {
|
||||
|
||||
int (*rx_fill)(struct mt76_dev *dev, struct mt76_queue *q, bool napi);
|
||||
|
||||
int (*rx_process)(struct mt76_dev *dev, struct mt76_queue *q, int budget);
|
||||
|
||||
void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
};
|
||||
|
||||
@@ -156,6 +158,9 @@ struct mt76_driver_ops {
|
||||
int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_txwi_cache *txwi,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta);
|
||||
|
||||
void (*rx_skb)(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
struct sk_buff *skb);
|
||||
};
|
||||
|
||||
struct mt76_dev {
|
||||
@@ -233,6 +238,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
|
||||
#define mt76_queue_dequeue(dev, ...) (dev)->mt76.queue_ops->dequeue(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_fill(dev, ...) (dev)->mt76.queue_ops->rx_fill(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_process(dev, ...) (dev)->mt76.queue_ops->rx_process(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
|
||||
|
||||
int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
|
||||
@@ -227,4 +227,7 @@ void mt76x2_pre_tbtt_tasklet(unsigned long data);
|
||||
|
||||
void mt76x2_txq_init(struct mt76x2_dev *dev, struct ieee80211_txq *txq);
|
||||
|
||||
void mt76x2_queue_rx_skb(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
struct sk_buff *skb);
|
||||
|
||||
#endif
|
||||
|
||||
+6
-77
@@ -122,13 +122,13 @@ mt76x2_init_tx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_process_rx_skb(struct mt76x2_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb)
|
||||
void mt76x2_queue_rx_skb(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
|
||||
void *rxwi = skb->data;
|
||||
|
||||
if (q == &dev->mt76.q_rx[MT_RXQ_MCU]) {
|
||||
if (q == &mdev->q_rx[MT_RXQ_MCU]) {
|
||||
skb_queue_tail(&dev->mcu.res_q, skb);
|
||||
wake_up(&dev->mcu.wait);
|
||||
return;
|
||||
@@ -143,77 +143,6 @@ mt76x2_process_rx_skb(struct mt76x2_dev *dev, struct mt76_queue *q,
|
||||
mt76x2_rx(dev, skb);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_add_fragment(struct mt76x2_dev *dev, struct mt76_queue *q, void *data,
|
||||
int len, bool more)
|
||||
{
|
||||
struct page *page = virt_to_head_page(data);
|
||||
int offset = data - page_address(page);
|
||||
struct sk_buff *skb = q->rx_head;
|
||||
|
||||
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, len,
|
||||
q->buf_size);
|
||||
|
||||
if (!more) {
|
||||
q->rx_head = NULL;
|
||||
mt76x2_process_rx_skb(dev, q, skb);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2_process_rx_queue(struct mt76x2_dev *dev, struct mt76_queue *q, int budget)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned char *data;
|
||||
int len;
|
||||
int done = 0;
|
||||
bool napi = q == &dev->mt76.q_rx[MT_RXQ_MAIN];
|
||||
bool more;
|
||||
|
||||
while (done < budget) {
|
||||
u32 info;
|
||||
|
||||
data = mt76_queue_dequeue(dev, q, false, &len, &info, &more);
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
if (q->rx_head) {
|
||||
mt76x2_add_fragment(dev, q, data, len, more);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb = build_skb(data, q->buf_size);
|
||||
if (!skb) {
|
||||
skb_free_frag(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_reserve(skb, q->buf_offset);
|
||||
if (skb->tail + len > skb->end) {
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (q == &dev->mt76.q_rx[MT_RXQ_MCU]) {
|
||||
u32 * rxfce = (u32 *) skb->cb;
|
||||
*rxfce = info;
|
||||
}
|
||||
|
||||
__skb_put(skb, len);
|
||||
done++;
|
||||
|
||||
if (more) {
|
||||
q->rx_head = skb;
|
||||
continue;
|
||||
}
|
||||
|
||||
mt76x2_process_rx_skb(dev, q, skb);
|
||||
}
|
||||
|
||||
mt76_queue_rx_fill(dev, q, napi);
|
||||
return done;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2_init_rx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc, int bufsize)
|
||||
@@ -254,7 +183,7 @@ mt76x2_dma_rx_poll(struct napi_struct *napi, int budget)
|
||||
struct mt76x2_dev *dev = container_of(napi, struct mt76x2_dev, napi);
|
||||
int done;
|
||||
|
||||
done = mt76x2_process_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], budget);
|
||||
done = mt76_queue_rx_process(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], budget);
|
||||
|
||||
if (done < budget) {
|
||||
napi_complete(napi);
|
||||
@@ -270,7 +199,7 @@ mt76x2_rx_tasklet(unsigned long data)
|
||||
struct mt76x2_dev *dev = (struct mt76x2_dev *) data;
|
||||
struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MCU];
|
||||
|
||||
mt76x2_process_rx_queue(dev, q, q->ndesc);
|
||||
mt76_queue_rx_process(dev, q, q->ndesc);
|
||||
|
||||
mt76x2_irq_enable(dev, MT_INT_RX_DONE(1));
|
||||
}
|
||||
|
||||
+2
-1
@@ -590,7 +590,8 @@ struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.fill_txwi = mt76x2_mac_write_txwi,
|
||||
.tx_queue_skb = mt76x2_tx_queue_skb
|
||||
.tx_queue_skb = mt76x2_tx_queue_skb,
|
||||
.rx_skb = mt76x2_queue_rx_skb,
|
||||
};
|
||||
struct ieee80211_hw *hw;
|
||||
struct mt76x2_dev *dev;
|
||||
|
||||
Reference in New Issue
Block a user