diff options
-rw-r--r-- | drivers/net/wireless/ath/wil6210/interrupt.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/netdev.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 16 |
5 files changed, 94 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 5fe985cd3dfd..8205d3e4ab66 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -104,14 +104,14 @@ static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) | |||
104 | clear_bit(wil_status_irqen, &wil->status); | 104 | clear_bit(wil_status_irqen, &wil->status); |
105 | } | 105 | } |
106 | 106 | ||
107 | static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) | 107 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil) |
108 | { | 108 | { |
109 | iowrite32(WIL6210_IMC_TX, wil->csr + | 109 | iowrite32(WIL6210_IMC_TX, wil->csr + |
110 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | 110 | HOSTADDR(RGF_DMA_EP_TX_ICR) + |
111 | offsetof(struct RGF_ICR, IMC)); | 111 | offsetof(struct RGF_ICR, IMC)); |
112 | } | 112 | } |
113 | 113 | ||
114 | static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) | 114 | void wil6210_unmask_irq_rx(struct wil6210_priv *wil) |
115 | { | 115 | { |
116 | iowrite32(WIL6210_IMC_RX, wil->csr + | 116 | iowrite32(WIL6210_IMC_RX, wil->csr + |
117 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | 117 | HOSTADDR(RGF_DMA_EP_RX_ICR) + |
@@ -182,13 +182,14 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | |||
182 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { | 182 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { |
183 | wil_dbg_irq(wil, "RX done\n"); | 183 | wil_dbg_irq(wil, "RX done\n"); |
184 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; | 184 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; |
185 | wil_rx_handle(wil); | 185 | wil_dbg_txrx(wil, "NAPI schedule\n"); |
186 | napi_schedule(&wil->napi_rx); | ||
186 | } | 187 | } |
187 | 188 | ||
188 | if (isr) | 189 | if (isr) |
189 | wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); | 190 | wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); |
190 | 191 | ||
191 | wil6210_unmask_irq_rx(wil); | 192 | /* Rx IRQ will be enabled when NAPI processing finished */ |
192 | 193 | ||
193 | return IRQ_HANDLED; | 194 | return IRQ_HANDLED; |
194 | } | 195 | } |
@@ -211,23 +212,17 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | |||
211 | wil6210_mask_irq_tx(wil); | 212 | wil6210_mask_irq_tx(wil); |
212 | 213 | ||
213 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { | 214 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { |
214 | uint i; | ||
215 | wil_dbg_irq(wil, "TX done\n"); | 215 | wil_dbg_irq(wil, "TX done\n"); |
216 | napi_schedule(&wil->napi_tx); | ||
216 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | 217 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; |
217 | for (i = 0; i < 24; i++) { | 218 | /* clear also all VRING interrupts */ |
218 | u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); | 219 | isr &= ~(BIT(25) - 1UL); |
219 | if (isr & mask) { | ||
220 | isr &= ~mask; | ||
221 | wil_dbg_irq(wil, "TX done(%i)\n", i); | ||
222 | wil_tx_complete(wil, i); | ||
223 | } | ||
224 | } | ||
225 | } | 220 | } |
226 | 221 | ||
227 | if (isr) | 222 | if (isr) |
228 | wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); | 223 | wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); |
229 | 224 | ||
230 | wil6210_unmask_irq_tx(wil); | 225 | /* Tx IRQ will be enabled when NAPI processing finished */ |
231 | 226 | ||
232 | return IRQ_HANDLED; | 227 | return IRQ_HANDLED; |
233 | } | 228 | } |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index a0478e2f6868..ea49c8a18e15 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -365,6 +365,9 @@ static int __wil_up(struct wil6210_priv *wil) | |||
365 | /* Rx VRING. After MAC and beacon */ | 365 | /* Rx VRING. After MAC and beacon */ |
366 | wil_rx_init(wil); | 366 | wil_rx_init(wil); |
367 | 367 | ||
368 | napi_enable(&wil->napi_rx); | ||
369 | napi_enable(&wil->napi_tx); | ||
370 | |||
368 | return 0; | 371 | return 0; |
369 | } | 372 | } |
370 | 373 | ||
@@ -381,6 +384,9 @@ int wil_up(struct wil6210_priv *wil) | |||
381 | 384 | ||
382 | static int __wil_down(struct wil6210_priv *wil) | 385 | static int __wil_down(struct wil6210_priv *wil) |
383 | { | 386 | { |
387 | napi_disable(&wil->napi_rx); | ||
388 | napi_disable(&wil->napi_tx); | ||
389 | |||
384 | if (wil->scan_request) { | 390 | if (wil->scan_request) { |
385 | cfg80211_scan_done(wil->scan_request, true); | 391 | cfg80211_scan_done(wil->scan_request, true); |
386 | wil->scan_request = NULL; | 392 | wil->scan_request = NULL; |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 098a8ec6b841..29dd1e58cb17 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -40,6 +40,55 @@ static const struct net_device_ops wil_netdev_ops = { | |||
40 | .ndo_validate_addr = eth_validate_addr, | 40 | .ndo_validate_addr = eth_validate_addr, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget) | ||
44 | { | ||
45 | struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, | ||
46 | napi_rx); | ||
47 | int quota = budget; | ||
48 | int done; | ||
49 | |||
50 | wil_rx_handle(wil, "a); | ||
51 | done = budget - quota; | ||
52 | |||
53 | if (done <= 1) { /* burst ends - only one packet processed */ | ||
54 | napi_complete(napi); | ||
55 | wil6210_unmask_irq_rx(wil); | ||
56 | wil_dbg_txrx(wil, "NAPI RX complete\n"); | ||
57 | } | ||
58 | |||
59 | wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done); | ||
60 | |||
61 | return done; | ||
62 | } | ||
63 | |||
64 | static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) | ||
65 | { | ||
66 | struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, | ||
67 | napi_tx); | ||
68 | int tx_done = 0; | ||
69 | uint i; | ||
70 | |||
71 | /* always process ALL Tx complete, regardless budget - it is fast */ | ||
72 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | ||
73 | struct vring *vring = &wil->vring_tx[i]; | ||
74 | |||
75 | if (!vring->va) | ||
76 | continue; | ||
77 | |||
78 | tx_done += wil_tx_complete(wil, i); | ||
79 | } | ||
80 | |||
81 | if (tx_done <= 1) { /* burst ends - only one packet processed */ | ||
82 | napi_complete(napi); | ||
83 | wil6210_unmask_irq_tx(wil); | ||
84 | wil_dbg_txrx(wil, "NAPI TX complete\n"); | ||
85 | } | ||
86 | |||
87 | wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done); | ||
88 | |||
89 | return min(tx_done, budget); | ||
90 | } | ||
91 | |||
43 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | 92 | void *wil_if_alloc(struct device *dev, void __iomem *csr) |
44 | { | 93 | { |
45 | struct net_device *ndev; | 94 | struct net_device *ndev; |
@@ -81,6 +130,11 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
81 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | 130 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); |
82 | wdev->netdev = ndev; | 131 | wdev->netdev = ndev; |
83 | 132 | ||
133 | netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, | ||
134 | WIL6210_NAPI_BUDGET); | ||
135 | netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, | ||
136 | WIL6210_NAPI_BUDGET); | ||
137 | |||
84 | wil_link_off(wil); | 138 | wil_link_off(wil); |
85 | 139 | ||
86 | return wil; | 140 | return wil; |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index dc183d573c08..bab50117383a 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -440,6 +440,7 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) | |||
440 | 440 | ||
441 | /* | 441 | /* |
442 | * Pass Rx packet to the netif. Update statistics. | 442 | * Pass Rx packet to the netif. Update statistics. |
443 | * Called in softirq context (NAPI poll). | ||
443 | */ | 444 | */ |
444 | static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | 445 | static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
445 | { | 446 | { |
@@ -448,10 +449,7 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
448 | 449 | ||
449 | skb_orphan(skb); | 450 | skb_orphan(skb); |
450 | 451 | ||
451 | if (in_interrupt()) | 452 | rc = netif_receive_skb(skb); |
452 | rc = netif_rx(skb); | ||
453 | else | ||
454 | rc = netif_rx_ni(skb); | ||
455 | 453 | ||
456 | if (likely(rc == NET_RX_SUCCESS)) { | 454 | if (likely(rc == NET_RX_SUCCESS)) { |
457 | ndev->stats.rx_packets++; | 455 | ndev->stats.rx_packets++; |
@@ -465,9 +463,9 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
465 | /** | 463 | /** |
466 | * Proceed all completed skb's from Rx VRING | 464 | * Proceed all completed skb's from Rx VRING |
467 | * | 465 | * |
468 | * Safe to call from IRQ | 466 | * Safe to call from NAPI poll, i.e. softirq with interrupts enabled |
469 | */ | 467 | */ |
470 | void wil_rx_handle(struct wil6210_priv *wil) | 468 | void wil_rx_handle(struct wil6210_priv *wil, int *quota) |
471 | { | 469 | { |
472 | struct net_device *ndev = wil_to_ndev(wil); | 470 | struct net_device *ndev = wil_to_ndev(wil); |
473 | struct vring *v = &wil->vring_rx; | 471 | struct vring *v = &wil->vring_rx; |
@@ -478,7 +476,8 @@ void wil_rx_handle(struct wil6210_priv *wil) | |||
478 | return; | 476 | return; |
479 | } | 477 | } |
480 | wil_dbg_txrx(wil, "%s()\n", __func__); | 478 | wil_dbg_txrx(wil, "%s()\n", __func__); |
481 | while (NULL != (skb = wil_vring_reap_rx(wil, v))) { | 479 | while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { |
480 | (*quota)--; | ||
482 | 481 | ||
483 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | 482 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
484 | skb->dev = ndev; | 483 | skb->dev = ndev; |
@@ -788,17 +787,20 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
788 | /** | 787 | /** |
789 | * Clean up transmitted skb's from the Tx VRING | 788 | * Clean up transmitted skb's from the Tx VRING |
790 | * | 789 | * |
790 | * Return number of descriptors cleared | ||
791 | * | ||
791 | * Safe to call from IRQ | 792 | * Safe to call from IRQ |
792 | */ | 793 | */ |
793 | void wil_tx_complete(struct wil6210_priv *wil, int ringid) | 794 | int wil_tx_complete(struct wil6210_priv *wil, int ringid) |
794 | { | 795 | { |
795 | struct net_device *ndev = wil_to_ndev(wil); | 796 | struct net_device *ndev = wil_to_ndev(wil); |
796 | struct device *dev = wil_to_dev(wil); | 797 | struct device *dev = wil_to_dev(wil); |
797 | struct vring *vring = &wil->vring_tx[ringid]; | 798 | struct vring *vring = &wil->vring_tx[ringid]; |
799 | int done = 0; | ||
798 | 800 | ||
799 | if (!vring->va) { | 801 | if (!vring->va) { |
800 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); | 802 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); |
801 | return; | 803 | return 0; |
802 | } | 804 | } |
803 | 805 | ||
804 | wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); | 806 | wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); |
@@ -847,7 +849,10 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
847 | d->dma.length = 0; | 849 | d->dma.length = 0; |
848 | d->dma.status = TX_DMA_STATUS_DU; | 850 | d->dma.status = TX_DMA_STATUS_DU; |
849 | vring->swtail = wil_vring_next_tail(vring); | 851 | vring->swtail = wil_vring_next_tail(vring); |
852 | done++; | ||
850 | } | 853 | } |
851 | if (wil_vring_avail_tx(vring) > vring->size/4) | 854 | if (wil_vring_avail_tx(vring) > vring->size/4) |
852 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | 855 | netif_tx_wake_all_queues(wil_to_ndev(wil)); |
856 | |||
857 | return done; | ||
853 | } | 858 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 484446e66c5a..2e3c26e1c975 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -34,9 +34,11 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
34 | 34 | ||
35 | #define WIL6210_MEM_SIZE (2*1024*1024UL) | 35 | #define WIL6210_MEM_SIZE (2*1024*1024UL) |
36 | 36 | ||
37 | #define WIL6210_RX_RING_SIZE (128) | 37 | #define WIL6210_RX_RING_SIZE (128) |
38 | #define WIL6210_TX_RING_SIZE (128) | 38 | #define WIL6210_TX_RING_SIZE (128) |
39 | #define WIL6210_MAX_TX_RINGS (24) | 39 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ |
40 | #define WIL6210_MAX_CID (8) /* HW limit */ | ||
41 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ | ||
40 | 42 | ||
41 | /* Hardware definitions begin */ | 43 | /* Hardware definitions begin */ |
42 | 44 | ||
@@ -239,6 +241,8 @@ struct wil6210_priv { | |||
239 | * - consumed in thread by wmi_event_worker | 241 | * - consumed in thread by wmi_event_worker |
240 | */ | 242 | */ |
241 | spinlock_t wmi_ev_lock; | 243 | spinlock_t wmi_ev_lock; |
244 | struct napi_struct napi_rx; | ||
245 | struct napi_struct napi_tx; | ||
242 | /* DMA related */ | 246 | /* DMA related */ |
243 | struct vring vring_rx; | 247 | struct vring vring_rx; |
244 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | 248 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; |
@@ -360,10 +364,12 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
360 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | 364 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); |
361 | 365 | ||
362 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | 366 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); |
363 | void wil_tx_complete(struct wil6210_priv *wil, int ringid); | 367 | int wil_tx_complete(struct wil6210_priv *wil, int ringid); |
368 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil); | ||
364 | 369 | ||
365 | /* RX API */ | 370 | /* RX API */ |
366 | void wil_rx_handle(struct wil6210_priv *wil); | 371 | void wil_rx_handle(struct wil6210_priv *wil, int *quota); |
372 | void wil6210_unmask_irq_rx(struct wil6210_priv *wil); | ||
367 | 373 | ||
368 | int wil_iftype_nl2wmi(enum nl80211_iftype type); | 374 | int wil_iftype_nl2wmi(enum nl80211_iftype type); |
369 | 375 | ||