Commit c3b744fd authored by Raju Rangoju's avatar Raju Rangoju Committed by Jakub Kicinski
Browse files

amd-xgbe: refactor the dma IRQ handling code path



Refactor the DMA interrupt bottom-half handling to improve the
readability, maintainability, without changing the intended behavior.

Signed-off-by: default avatarRaju Rangoju <Raju.Rangoju@amd.com>
Link: https://patch.msgid.link/20251129175016.3034185-2-Raju.Rangoju@amd.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent aee0f01b
Loading
Loading
Loading
Loading
+40 −20
Original line number Diff line number Diff line
@@ -367,10 +367,11 @@ static irqreturn_t xgbe_ecc_isr(int irq, void *data)
static void xgbe_isr_bh_work(struct work_struct *work)
{
	struct xgbe_prv_data *pdata = from_work(pdata, work, dev_bh_work);
	unsigned int mac_isr, mac_tssr, mac_mdioisr;
	struct xgbe_hw_if *hw_if = &pdata->hw_if;
	struct xgbe_channel *channel;
	bool per_ch_irq, ti, ri, rbu, fbe;
	unsigned int dma_isr, dma_ch_isr;
	unsigned int mac_isr, mac_tssr, mac_mdioisr;
	struct xgbe_channel *channel;
	unsigned int i;

	/* The DMA interrupt status register also reports MAC and MTL
@@ -384,43 +385,62 @@ static void xgbe_isr_bh_work(struct work_struct *work)
	netif_dbg(pdata, intr, pdata->netdev, "DMA_ISR=%#010x\n", dma_isr);

	for (i = 0; i < pdata->channel_count; i++) {
		bool schedule_napi = false;
		struct napi_struct *napi;

		if (!(dma_isr & (1 << i)))
			continue;

		channel = pdata->channel[i];

		dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR);

		/* Precompute flags once */
		ti  = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI);
		ri  = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI);
		rbu = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU);
		fbe = !!XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE);

		netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\n",
			  i, dma_ch_isr);

		/* The TI or RI interrupt bits may still be set even if using
		 * per channel DMA interrupts. Check to be sure those are not
		 * enabled before using the private data napi structure.
		per_ch_irq = pdata->per_channel_irq;

		/*
		 * Decide which NAPI to use and whether to schedule:
		 * - When not using per-channel IRQs: schedule on global NAPI
		 *   if TI or RI are set.
		 */
		if (!pdata->per_channel_irq &&
		    (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) ||
		     XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI))) {
			if (napi_schedule_prep(&pdata->napi)) {
				/* Disable Tx and Rx interrupts */
		if (!per_ch_irq && (ti || ri))
			schedule_napi = true;

		napi = per_ch_irq ? &channel->napi : &pdata->napi;

		if (schedule_napi && napi_schedule_prep(napi)) {
			/* Disable interrupts appropriately before polling */
			xgbe_disable_rx_tx_ints(pdata);

			/* Turn on polling */
				__napi_schedule(&pdata->napi);
			}
			__napi_schedule(napi);
		} else {
			/* Don't clear Rx/Tx status if doing per channel DMA
			 * interrupts, these will be cleared by the ISR for
			 * per channel DMA interrupts.
			/*
			 * Don't clear Rx/Tx status if doing per-channel DMA
			 * interrupts; those bits will be serviced/cleared by
			 * the per-channel ISR/NAPI. In non-per-channel mode
			 * when we're not scheduling NAPI here, ensure we don't
			 * accidentally clear TI/RI in HW: zero them in the
			 * local copy so that the eventual write-back does not
			 * clear TI/RI.
			 */
			XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, TI, 0);
			XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, RI, 0);
		}

		if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU))
		if (rbu)
			pdata->ext_stats.rx_buffer_unavailable++;

		/* Restart the device on a Fatal Bus Error */
		if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE))
		if (fbe)
			schedule_work(&pdata->restart_work);

		/* Clear interrupt signals */