| @@ -148,12 +148,14 @@ static void stmmac_verify_args(void) · 147 unmodified lines |
| 148 | 148 | static void stmmac_disable_all_queues(struct stmmac_priv *priv) |
| 149 | 149 | { |
| 150 | 150 | u32 rx_queues_cnt = priv->plat->rx_queues_to_use; |
| 151 | + u32 tx_queues_cnt = priv->plat->tx_queues_to_use; |
| 152 | + u32 maxq = max(rx_queues_cnt, tx_queues_cnt); |
| 151 | 153 | u32 queue; |
| 152 | 154 | |
| 153 | | − for (queue = 0; queue < rx_queues_cnt; queue++) { |
| 154 | | − struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; |
| 155 | + for (queue = 0; queue < maxq; queue++) { |
| 156 | + struct stmmac_channel *ch = &priv->channel[queue]; |
| 155 | 157 | |
| 156 | | − napi_disable(&rx_q->napi); |
| 158 | + napi_disable(&ch->napi); |
| 157 | 159 | } |
| 158 | 160 | } |
| 159 | 161 | |
| @@ -164,12 +166,14 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv) · 4 unmodified lines |
| 164 | 166 | static void stmmac_enable_all_queues(struct stmmac_priv *priv) |
| 165 | 167 | { |
| 166 | 168 | u32 rx_queues_cnt = priv->plat->rx_queues_to_use; |
| 169 | + u32 tx_queues_cnt = priv->plat->tx_queues_to_use; |
| 170 | + u32 maxq = max(rx_queues_cnt, tx_queues_cnt); |
| 167 | 171 | u32 queue; |
| 168 | 172 | |
| 169 | | − for (queue = 0; queue < rx_queues_cnt; queue++) { |
| 170 | | − struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; |
| 173 | + for (queue = 0; queue < maxq; queue++) { |
| 174 | + struct stmmac_channel *ch = &priv->channel[queue]; |
| 171 | 175 | |
| 172 | | − napi_enable(&rx_q->napi); |
| 176 | + napi_enable(&ch->napi); |
| 173 | 177 | } |
| 174 | 178 | } |
| 175 | 179 | |
| @@ -1843,18 +1847,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) · 1667 unmodified lines |
| 1843 | 1847 | * @queue: TX queue index |
| 1844 | 1848 | * Description: it reclaims the transmit resources after transmission completes. |
| 1845 | 1849 | */ |
| 1846 | | −static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) |
| 1850 | +static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) |
| 1847 | 1851 | { |
| 1848 | 1852 | struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; |
| 1849 | 1853 | unsigned int bytes_compl = 0, pkts_compl = 0; |
| 1850 | | − unsigned int entry; |
| 1854 | + unsigned int entry, count = 0; |
| 1851 | 1855 | |
| 1852 | | − netif_tx_lock(priv->dev); |
| 1856 | + __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue)); |
| 1853 | 1857 | |
| 1854 | 1858 | priv->xstats.tx_clean++; |
| 1855 | 1859 | |
| 1856 | 1860 | entry = tx_q->dirty_tx; |
| 1857 | | − while (entry != tx_q->cur_tx) { |
| 1861 | + while ((entry != tx_q->cur_tx) && (count < budget)) { |
| 1858 | 1862 | struct sk_buff *skb = tx_q->tx_skbuff[entry]; |
| 1859 | 1863 | struct dma_desc *p; |
| 1860 | 1864 | int status; |
| @@ -1870,6 +1874,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) · 9 unmodified lines |
| 1870 | 1874 | if (unlikely(status & tx_dma_own)) |
| 1871 | 1875 | break; |
| 1872 | 1876 | |
| 1877 | + count++; |
| 1878 | + |
| 1873 | 1879 | /* Make sure descriptor fields are read after reading |
| 1874 | 1880 | * the own bit. |
| 1875 | 1881 | */ |
| @@ -1937,7 +1943,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) · 61 unmodified lines |
| 1937 | 1943 | stmmac_enable_eee_mode(priv); |
| 1938 | 1944 | mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); |
| 1939 | 1945 | } |
| 1940 | | − netif_tx_unlock(priv->dev); |
| 1946 | + |
| 1947 | + __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); |
| 1948 | + |
| 1949 | + return count; |
| 1941 | 1950 | } |
| 1942 | 1951 | |
| 1943 | 1952 | /** |
| @@ -2020,6 +2029,33 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv) · 76 unmodified lines |
| 2020 | 2029 | return false; |
| 2021 | 2030 | } |
| 2022 | 2031 | |
| 2032 | +static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan) |
| 2033 | +{ |
| 2034 | + int status = stmmac_dma_interrupt_status(priv, priv->ioaddr, |
| 2035 | + &priv->xstats, chan); |
| 2036 | + struct stmmac_channel *ch = &priv->channel[chan]; |
| 2037 | + bool needs_work = false; |
| 2038 | + |
| 2039 | + if ((status & handle_rx) && ch->has_rx) { |
| 2040 | + needs_work = true; |
| 2041 | + } else { |
| 2042 | + status &= ~handle_rx; |
| 2043 | + } |
| 2044 | + |
| 2045 | + if ((status & handle_tx) && ch->has_tx) { |
| 2046 | + needs_work = true; |
| 2047 | + } else { |
| 2048 | + status &= ~handle_tx; |
| 2049 | + } |
| 2050 | + |
| 2051 | + if (needs_work && napi_schedule_prep(&ch->napi)) { |
| 2052 | + stmmac_disable_dma_irq(priv, priv->ioaddr, chan); |
| 2053 | + __napi_schedule(&ch->napi); |
| 2054 | + } |
| 2055 | + |
| 2056 | + return status; |
| 2057 | +} |
| 2058 | + |
| 2023 | 2059 | /** |
| 2024 | 2060 | * stmmac_dma_interrupt - DMA ISR |
| 2025 | 2061 | * @priv: driver private structure |
| @@ -2034,57 +2070,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) · 8 unmodified lines |
| 2034 | 2070 | u32 channels_to_check = tx_channel_count > rx_channel_count ? |
| 2035 | 2071 | tx_channel_count : rx_channel_count; |
| 2036 | 2072 | u32 chan; |
| 2037 | | − bool poll_scheduled = false; |
| 2038 | 2073 | int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)]; |
| 2039 | 2074 | |
| 2040 | 2075 | /* Make sure we never check beyond our status buffer. */ |
| 2041 | 2076 | if (WARN_ON_ONCE(channels_to_check > ARRAY_SIZE(status))) |
| 2042 | 2077 | channels_to_check = ARRAY_SIZE(status); |
| 2043 | 2078 | |
| 2044 | | − /* Each DMA channel can be used for rx and tx simultaneously, yet |
| 2045 | | − * napi_struct is embedded in struct stmmac_rx_queue rather than in a |
| 2046 | | − * stmmac_channel struct. |
| 2047 | | − * Because of this, stmmac_poll currently checks (and possibly wakes) |
| 2048 | | − * all tx queues rather than just a single tx queue. |
| 2049 | | − */ |
| 2050 | 2079 | for (chan = 0; chan < channels_to_check; chan++) |
| 2051 | | − status[chan] = stmmac_dma_interrupt_status(priv, priv->ioaddr, |
| 2052 | | − &priv->xstats, chan); |
| 2053 | | − |
| 2054 | | − for (chan = 0; chan < rx_channel_count; chan++) { |
| 2055 | | − if (likely(status[chan] & handle_rx)) { |
| 2056 | | − struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan]; |
| 2057 | | − |
| 2058 | | − if (likely(napi_schedule_prep(&rx_q->napi))) { |
| 2059 | | − stmmac_disable_dma_irq(priv, priv->ioaddr, chan); |
| 2060 | | − __napi_schedule(&rx_q->napi); |
| 2061 | | − poll_scheduled = true; |
| 2062 | | − } |
| 2063 | | − } |
| 2064 | | − } |
| 2065 | | − |
| 2066 | | − /* If we scheduled poll, we already know that tx queues will be checked. |
| 2067 | | − * If we didn't schedule poll, see if any DMA channel (used by tx) has a |
| 2068 | | − * completed transmission, if so, call stmmac_poll (once). |
| 2069 | | − */ |
| 2070 | | − if (!poll_scheduled) { |
| 2071 | | − for (chan = 0; chan < tx_channel_count; chan++) { |
| 2072 | | − if (status[chan] & handle_tx) { |
| 2073 | | − /* It doesn't matter what rx queue we choose |
| 2074 | | − * here. We use 0 since it always exists. |
| 2075 | | − */ |
| 2076 | | − struct stmmac_rx_queue *rx_q = |
| 2077 | | − &priv->rx_queue[0]; |
| 2078 | | − |
| 2079 | | − if (likely(napi_schedule_prep(&rx_q->napi))) { |
| 2080 | | − stmmac_disable_dma_irq(priv, |
| 2081 | | − priv->ioaddr, chan); |
| 2082 | | − __napi_schedule(&rx_q->napi); |
| 2083 | | − } |
| 2084 | | − break; |
| 2085 | | − } |
| 2086 | | − } |
| 2087 | | − } |
| 2080 | + status[chan] = stmmac_napi_check(priv, chan); |
| 2088 | 2081 | |
| 2089 | 2082 | for (chan = 0; chan < tx_channel_count; chan++) { |
| 2090 | 2083 | if (unlikely(status[chan] & tx_hard_error_bump_tc)) { |
| @@ -2233,6 +2226,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) · 142 unmodified lines |
| 2233 | 2226 | return ret; |
| 2234 | 2227 | } |
| 2235 | 2228 | |
| 2229 | +static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue) |
| 2230 | +{ |
| 2231 | + struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; |
| 2232 | + |
| 2233 | + mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer)); |
| 2234 | +} |
| 2235 | + |
| 2236 | 2236 | /** |
| 2237 | 2237 | * stmmac_tx_timer - mitigation sw timer for tx. |
| 2238 | 2238 | * @data: data pointer |
| @@ -2241,13 +2241,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) · 2 unmodified lines |
| 2241 | 2241 | */ |
| 2242 | 2242 | static void stmmac_tx_timer(struct timer_list *t) |
| 2243 | 2243 | { |
| 2244 | | − struct stmmac_priv *priv = from_timer(priv, t, txtimer); |
| 2245 | | − u32 tx_queues_count = priv->plat->tx_queues_to_use; |
| 2246 | | − u32 queue; |
| 2244 | + struct stmmac_tx_queue *tx_q = from_timer(tx_q, t, txtimer); |
| 2245 | + struct stmmac_priv *priv = tx_q->priv_data; |
| 2246 | + struct stmmac_channel *ch; |
| 2247 | + |
| 2248 | + ch = &priv->channel[tx_q->queue_index]; |
| 2247 | 2249 | |
| 2248 | | − /* let's scan all the tx queues */ |
| 2249 | | − for (queue = 0; queue < tx_queues_count; queue++) |
| 2250 | | − stmmac_tx_clean(priv, queue); |
| 2250 | + if (likely(napi_schedule_prep(&ch->napi))) |
| 2251 | + __napi_schedule(&ch->napi); |
| 2251 | 2252 | } |
| 2252 | 2253 | |
| 2253 | 2254 | /** |
| @@ -2260,11 +2261,17 @@ static void stmmac_tx_timer(struct timer_list *t) · 6 unmodified lines |
| 2260 | 2261 | */ |
| 2261 | 2262 | static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) |
| 2262 | 2263 | { |
| 2264 | + u32 tx_channel_count = priv->plat->tx_queues_to_use; |
| 2265 | + u32 chan; |
| 2266 | + |
| 2263 | 2267 | priv->tx_coal_frames = STMMAC_TX_FRAMES; |
| 2264 | 2268 | priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; |
| 2265 | | − timer_setup(&priv->txtimer, stmmac_tx_timer, 0); |
| 2266 | | − priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); |
| 2267 | | − add_timer(&priv->txtimer); |
| 2269 | + |
| 2270 | + for (chan = 0; chan < tx_channel_count; chan++) { |
| 2271 | + struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan]; |
| 2272 | + |
| 2273 | + timer_setup(&tx_q->txtimer, stmmac_tx_timer, 0); |
| 2274 | + } |
| 2268 | 2275 | } |
| 2269 | 2276 | |
| 2270 | 2277 | static void stmmac_set_rings_length(struct stmmac_priv *priv) |
| @@ -2592,6 +2599,7 @@ static void stmmac_hw_teardown(struct net_device *dev) · 321 unmodified lines |
| 2592 | 2599 | static int stmmac_open(struct net_device *dev) |
| 2593 | 2600 | { |
| 2594 | 2601 | struct stmmac_priv *priv = netdev_priv(dev); |
| 2602 | + u32 chan; |
| 2595 | 2603 | int ret; |
| 2596 | 2604 | |
| 2597 | 2605 | stmmac_check_ether_addr(priv); |
| @@ -2688,7 +2696,9 @@ irq_error: · 90 unmodified lines |
| 2688 | 2696 | if (dev->phydev) |
| 2689 | 2697 | phy_stop(dev->phydev); |
| 2690 | 2698 | |
| 2691 | | − del_timer_sync(&priv->txtimer); |
| 2699 | + for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) |
| 2700 | + del_timer_sync(&priv->tx_queue[chan].txtimer); |
| 2701 | + |
| 2692 | 2702 | stmmac_hw_teardown(dev); |
| 2693 | 2703 | init_error: |
| 2694 | 2704 | free_dma_desc_resources(priv); |
| @@ -2708,6 +2718,7 @@ dma_desc_error: · 13 unmodified lines |
| 2708 | 2718 | static int stmmac_release(struct net_device *dev) |
| 2709 | 2719 | { |
| 2710 | 2720 | struct stmmac_priv *priv = netdev_priv(dev); |
| 2721 | + u32 chan; |
| 2711 | 2722 | |
| 2712 | 2723 | if (priv->eee_enabled) |
| 2713 | 2724 | del_timer_sync(&priv->eee_ctrl_timer); |
| @@ -2722,7 +2733,8 @@ static int stmmac_release(struct net_device *dev) · 8 unmodified lines |
| 2722 | 2733 | |
| 2723 | 2734 | stmmac_disable_all_queues(priv); |
| 2724 | 2735 | |
| 2725 | | − del_timer_sync(&priv->txtimer); |
| 2736 | + for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) |
| 2737 | + del_timer_sync(&priv->tx_queue[chan].txtimer); |
| 2726 | 2738 | |
| 2727 | 2739 | /* Free the IRQ lines */ |
| 2728 | 2740 | free_irq(dev->irq, dev); |
| @@ -2936,14 +2948,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) · 207 unmodified lines |
| 2936 | 2948 | priv->xstats.tx_tso_nfrags += nfrags; |
| 2937 | 2949 | |
| 2938 | 2950 | /* Manage tx mitigation */ |
| 2939 | | − priv->tx_count_frames += nfrags + 1; |
| 2940 | | − if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { |
| 2941 | | − mod_timer(&priv->txtimer, |
| 2942 | | − STMMAC_COAL_TIMER(priv->tx_coal_timer)); |
| 2943 | | − } else { |
| 2944 | | − priv->tx_count_frames = 0; |
| 2951 | + tx_q->tx_count_frames += nfrags + 1; |
| 2952 | + if (priv->tx_coal_frames <= tx_q->tx_count_frames) { |
| 2945 | 2953 | stmmac_set_tx_ic(priv, desc); |
| 2946 | 2954 | priv->xstats.tx_set_ic_bit++; |
| 2955 | + tx_q->tx_count_frames = 0; |
| 2956 | + } else { |
| 2957 | + stmmac_tx_timer_arm(priv, queue); |
| 2947 | 2958 | } |
| 2948 | 2959 | |
| 2949 | 2960 | skb_tx_timestamp(skb); |
| @@ -3146,14 +3157,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) · 196 unmodified lines |
| 3146 | 3157 | * This approach takes care about the fragments: desc is the first |
| 3147 | 3158 | * element in case of no SG. |
| 3148 | 3159 | */ |
| 3149 | | − priv->tx_count_frames += nfrags + 1; |
| 3150 | | − if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { |
| 3151 | | − mod_timer(&priv->txtimer, |
| 3152 | | − STMMAC_COAL_TIMER(priv->tx_coal_timer)); |
| 3153 | | − } else { |
| 3154 | | − priv->tx_count_frames = 0; |
| 3160 | + tx_q->tx_count_frames += nfrags + 1; |
| 3161 | + if (priv->tx_coal_frames <= tx_q->tx_count_frames) { |
| 3155 | 3162 | stmmac_set_tx_ic(priv, desc); |
| 3156 | 3163 | priv->xstats.tx_set_ic_bit++; |
| 3164 | + tx_q->tx_count_frames = 0; |
| 3165 | + } else { |
| 3166 | + stmmac_tx_timer_arm(priv, queue); |
| 3157 | 3167 | } |
| 3158 | 3168 | |
| 3159 | 3169 | skb_tx_timestamp(skb); |
| @@ -3199,6 +3209,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) · 39 unmodified lines |
| 3199 | 3209 | netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); |
| 3200 | 3210 | |
| 3201 | 3211 | stmmac_enable_dma_transmission(priv, priv->ioaddr); |
| 3212 | + |
| 3202 | 3213 | stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue); |
| 3203 | 3214 | |
| 3204 | 3215 | return NETDEV_TX_OK; |
| @@ -3319,6 +3330,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) · 114 unmodified lines |
| 3319 | 3330 | static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) |
| 3320 | 3331 | { |
| 3321 | 3332 | struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; |
| 3333 | + struct stmmac_channel *ch = &priv->channel[queue]; |
| 3322 | 3334 | unsigned int entry = rx_q->cur_rx; |
| 3323 | 3335 | int coe = priv->hw->rx_csum; |
| 3324 | 3336 | unsigned int next_entry; |
| @@ -3491,7 +3503,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) · 166 unmodified lines |
| 3491 | 3503 | else |
| 3492 | 3504 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 3493 | 3505 | |
| 3494 | | − napi_gro_receive(&rx_q->napi, skb); |
| 3506 | + napi_gro_receive(&ch->napi, skb); |
| 3495 | 3507 | |
| 3496 | 3508 | priv->dev->stats.rx_packets++; |
| 3497 | 3509 | priv->dev->stats.rx_bytes += frame_len; |
| @@ -3514,27 +3526,33 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) · 16 unmodified lines |
| 3514 | 3526 | * Description : |
| 3515 | 3527 | * To look at the incoming frames and clear the tx resources. |
| 3516 | 3528 | */ |
| 3517 | | −static int stmmac_poll(struct napi_struct *napi, int budget) |
| 3529 | +static int stmmac_napi_poll(struct napi_struct *napi, int budget) |
| 3518 | 3530 | { |
| 3519 | | − struct stmmac_rx_queue *rx_q = |
| 3520 | | − container_of(napi, struct stmmac_rx_queue, napi); |
| 3521 | | − struct stmmac_priv *priv = rx_q->priv_data; |
| 3522 | | − u32 tx_count = priv->plat->tx_queues_to_use; |
| 3523 | | − u32 chan = rx_q->queue_index; |
| 3524 | | − int work_done = 0; |
| 3525 | | − u32 queue; |
| 3531 | + struct stmmac_channel *ch = |
| 3532 | + container_of(napi, struct stmmac_channel, napi); |
| 3533 | + struct stmmac_priv *priv = ch->priv_data; |
| 3534 | + int work_done = 0, work_rem = budget; |
| 3535 | + u32 chan = ch->index; |
| 3526 | 3536 | |
| 3527 | 3537 | priv->xstats.napi_poll++; |
| 3528 | 3538 | |
| 3529 | | − /* check all the queues */ |
| 3530 | | − for (queue = 0; queue < tx_count; queue++) |
| 3531 | | − stmmac_tx_clean(priv, queue); |
| 3539 | + if (ch->has_tx) { |
| 3540 | + int done = stmmac_tx_clean(priv, work_rem, chan); |
| 3532 | 3541 | |
| 3533 | | − work_done = stmmac_rx(priv, budget, rx_q->queue_index); |
| 3534 | | − if (work_done < budget) { |
| 3535 | | − napi_complete_done(napi, work_done); |
| 3536 | | − stmmac_enable_dma_irq(priv, priv->ioaddr, chan); |
| 3542 | + work_done += done; |
| 3543 | + work_rem -= done; |
| 3544 | + } |
| 3545 | + |
| 3546 | + if (ch->has_rx) { |
| 3547 | + int done = stmmac_rx(priv, work_rem, chan); |
| 3548 | + |
| 3549 | + work_done += done; |
| 3550 | + work_rem -= done; |
| 3537 | 3551 | } |
| 3552 | + |
| 3553 | + if (work_done < budget && napi_complete_done(napi, work_done)) |
| 3554 | + stmmac_enable_dma_irq(priv, priv->ioaddr, chan); |
| 3555 | + |
| 3538 | 3556 | return work_done; |
| 3539 | 3557 | } |
| 3540 | 3558 | |
| @@ -4198,8 +4216,8 @@ int stmmac_dvr_probe(struct device *device, · 657 unmodified lines |
| 4198 | 4216 | { |
| 4199 | 4217 | struct net_device *ndev = NULL; |
| 4200 | 4218 | struct stmmac_priv *priv; |
| 4219 | + u32 queue, maxq; |
| 4201 | 4220 | int ret = 0; |
| 4202 | | − u32 queue; |
| 4203 | 4221 | |
| 4204 | 4222 | ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv), |
| 4205 | 4223 | MTL_MAX_TX_QUEUES, |
| @@ -4322,11 +4340,22 @@ int stmmac_dvr_probe(struct device *device, · 116 unmodified lines |
| 4322 | 4340 | "Enable RX Mitigation via HW Watchdog Timer\n"); |
| 4323 | 4341 | } |
| 4324 | 4342 | |
| 4325 | | − for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { |
| 4326 | | − struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; |
| 4343 | + /* Setup channels NAPI */ |
| 4344 | + maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use); |
| 4327 | 4345 | |
| 4328 | | − netif_napi_add(ndev, &rx_q->napi, stmmac_poll, |
| 4329 | | − (8 * priv->plat->rx_queues_to_use)); |
| 4346 | + for (queue = 0; queue < maxq; queue++) { |
| 4347 | + struct stmmac_channel *ch = &priv->channel[queue]; |
| 4348 | + |
| 4349 | + ch->priv_data = priv; |
| 4350 | + ch->index = queue; |
| 4351 | + |
| 4352 | + if (queue < priv->plat->rx_queues_to_use) |
| 4353 | + ch->has_rx = true; |
| 4354 | + if (queue < priv->plat->tx_queues_to_use) |
| 4355 | + ch->has_tx = true; |
| 4356 | + |
| 4357 | + netif_napi_add(ndev, &ch->napi, stmmac_napi_poll, |
| 4358 | + NAPI_POLL_WEIGHT); |
| 4330 | 4359 | } |
| 4331 | 4360 | |
| 4332 | 4361 | mutex_init(&priv->lock); |
| @@ -4372,10 +4401,10 @@ error_netdev_register: · 39 unmodified lines |
| 4372 | 4401 | priv->hw->pcs != STMMAC_PCS_RTBI) |
| 4373 | 4402 | stmmac_mdio_unregister(ndev); |
| 4374 | 4403 | error_mdio_register: |
| 4375 | | − for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { |
| 4376 | | − struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; |
| 4404 | + for (queue = 0; queue < maxq; queue++) { |
| 4405 | + struct stmmac_channel *ch = &priv->channel[queue]; |
| 4377 | 4406 | |
| 4378 | | − netif_napi_del(&rx_q->napi); |
| 4407 | + netif_napi_del(&ch->napi); |
| 4379 | 4408 | } |
| 4380 | 4409 | error_hw_init: |
| 4381 | 4410 | destroy_workqueue(priv->wq); |