Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'amd-xgbe-schedule-napi-on-rbu-event'

Raju Rangoju says:

====================
amd-xgbe: schedule NAPI on RBU event

During the RX overload the Rx buffers may not be refilled, trying to
schedule the NAPI when an Rx Buffer Unavailable is signaled may help in
improving the such situation, in case we missed an IRQ.
====================

Link: https://patch.msgid.link/20251129175016.3034185-1-Raju.Rangoju@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+53 -22
+53 -22
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
··· 367 367 static void xgbe_isr_bh_work(struct work_struct *work) 368 368 { 369 369 struct xgbe_prv_data *pdata = from_work(pdata, work, dev_bh_work); 370 - struct xgbe_hw_if *hw_if = &pdata->hw_if; 371 - struct xgbe_channel *channel; 372 - unsigned int dma_isr, dma_ch_isr; 373 370 unsigned int mac_isr, mac_tssr, mac_mdioisr; 371 + struct xgbe_hw_if *hw_if = &pdata->hw_if; 372 + bool per_ch_irq, ti, ri, rbu, fbe; 373 + unsigned int dma_isr, dma_ch_isr; 374 + struct xgbe_channel *channel; 374 375 unsigned int i; 375 376 376 377 /* The DMA interrupt status register also reports MAC and MTL ··· 385 384 netif_dbg(pdata, intr, pdata->netdev, "DMA_ISR=%#010x\n", dma_isr); 386 385 387 386 for (i = 0; i < pdata->channel_count; i++) { 387 + bool schedule_napi = false; 388 + struct napi_struct *napi; 389 + 388 390 if (!(dma_isr & (1 << i))) 389 391 continue; 390 392 391 393 channel = pdata->channel[i]; 392 394 393 395 dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); 396 + 397 + /* Precompute flags once */ 398 + ti = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI); 399 + ri = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI); 400 + rbu = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU); 401 + fbe = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE); 402 + 394 403 netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\n", 395 404 i, dma_ch_isr); 396 405 397 - /* The TI or RI interrupt bits may still be set even if using 398 - * per channel DMA interrupts. Check to be sure those are not 399 - * enabled before using the private data napi structure. 400 - */ 401 - if (!pdata->per_channel_irq && 402 - (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || 403 - XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI))) { 404 - if (napi_schedule_prep(&pdata->napi)) { 405 - /* Disable Tx and Rx interrupts */ 406 - xgbe_disable_rx_tx_ints(pdata); 406 + per_ch_irq = pdata->per_channel_irq; 407 407 408 - /* Turn on polling */ 409 - __napi_schedule(&pdata->napi); 408 + /* 409 + * Decide which NAPI to use and whether to schedule: 410 + * - When not using per-channel IRQs: schedule on global NAPI 411 + * if TI or RI are set. 412 + * - RBU should also trigger NAPI (either per-channel or global) 413 + * to allow refill. 414 + */ 415 + if (!per_ch_irq && (ti || ri)) 416 + schedule_napi = true; 417 + 418 + if (rbu) { 419 + schedule_napi = true; 420 + pdata->ext_stats.rx_buffer_unavailable++; 421 + } 422 + 423 + napi = per_ch_irq ? &channel->napi : &pdata->napi; 424 + 425 + if (schedule_napi && napi_schedule_prep(napi)) { 426 + /* Disable interrupts appropriately before polling */ 427 + if (per_ch_irq) { 428 + if (pdata->channel_irq_mode) 429 + xgbe_disable_rx_tx_int(pdata, channel); 430 + else 431 + disable_irq_nosync(channel->dma_irq); 432 + } else { 433 + xgbe_disable_rx_tx_ints(pdata); 410 434 } 435 + 436 + /* Turn on polling */ 437 + __napi_schedule(napi); 411 438 } else { 412 - /* Don't clear Rx/Tx status if doing per channel DMA 413 - * interrupts, these will be cleared by the ISR for 414 - * per channel DMA interrupts. 439 + /* 440 + * Don't clear Rx/Tx status if doing per-channel DMA 441 + * interrupts; those bits will be serviced/cleared by 442 + * the per-channel ISR/NAPI. In non-per-channel mode 443 + * when we're not scheduling NAPI here, ensure we don't 444 + * accidentally clear TI/RI in HW: zero them in the 445 + * local copy so that the eventual write-back does not 446 + * clear TI/RI. 415 447 */ 416 448 XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, TI, 0); 417 449 XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, RI, 0); 418 450 } 419 451 420 - if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU)) 421 - pdata->ext_stats.rx_buffer_unavailable++; 422 - 423 452 /* Restart the device on a Fatal Bus Error */ 424 - if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE)) 453 + if (fbe) 425 454 schedule_work(&pdata->restart_work); 426 455 427 456 /* Clear interrupt signals */