From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 311B8366548; Fri, 8 May 2026 12:18:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778242727; cv=none; b=UDGQlPhTz9Yt04yTBB3z9jstHekQzfVB7+TzEnNDyHVpR5WMnUID8LbXoDX1uHzcUTlGpEzIwLuwPwX3PJ+uGEn2z++Rd0o9Ntjr+oNxvbjnOxU1nHAYY0Da4bu8ao7UP7xY7azWqvOaa7GteZW678X53Yzsqc5tBScibFQ9kZM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778242727; c=relaxed/simple; bh=bY2iNMRf+9sonb6hW8ojCMp7LBejg47/hzDwyVV9Djo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lURRNrFlrrHtr93pC8t4xC+UOlgfQaTnFZmcPyEif4vyQm+emNKDCNkoeUgyADcE5BcJov9UWz2U8/4C7k1IqoQ6AEkQYxo8gFyINdw5tcpAghiQVduoprgbxeCwvzTQ0hib5UMoNULdhA47avJI1T3932jfccj7t0sa9E2LNg4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn; spf=pass smtp.mailfrom=realsil.com.cn; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b=cGxc8rti; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realsil.com.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realsil.com.cn header.i=@realsil.com.cn header.b="cGxc8rti" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 648CICqnC3782632, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1778242692; bh=CBDfAUXgteydMhItpFNxK4UGgWdqPDRdUcn95SzBiH0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=cGxc8rtiHSHO6f68MkTOXzYXgrV8B6LLBYrW99y6TxnQFJox6uL6ASRMMl2meHytU cMGvCDK2+Uui9uuAWy0n/ZVnEtuZuc0yHab7Y2bNx/qXEzt7Ut1imLyHu2mnk0dswe jyxmSjRFTEW1UIEMoXjDn3SRES8pzl15hyt7sCHN7a+ZrK3AuTHkxkX2VrFwcjjVoZ djPty4uYm5a8ujxeVI/j+EZ4YXOPQP30S142numdPNajy1XsAyYOJGk5/sCDTggP+0 aK+aeUHt7BTyY4N8oNwscXf168TcB7KFeSdSstT/+tc1yzHx4Aj/D0JfkusoOD99Cq RrgHBnEG6XTsQ== Received: from RS-EX-MBS1.realsil.com.cn ([172.29.17.101]) by rtits2.realtek.com.tw (8.15.2/3.27/5.94) with ESMTPS id 648CICqnC3782632 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 8 May 2026 20:18:12 +0800 Received: from RS-EX-MBS2.realsil.com.cn (172.29.17.102) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Fri, 8 May 2026 20:18:12 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS2.realsil.com.cn (172.29.17.102) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Fri, 8 May 2026 20:18:12 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [Patch net-next v2 1/7] r8169: add support for multi irqs Date: Fri, 8 May 2026 20:17:55 +0800 Message-ID: <20260508121802.2010-2-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260508121802.2010-1-javen_xu@realsil.com.cn> References: <20260508121802.2010-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain From: Javen Xu RSS uses multi rx queues to receive packets, and each rx queue needs one irq and napi. So this patch adds support for multi irqs and napi here. Signed-off-by: Javen Xu --- Changes in v2: - remove some unused definitions, such as index, name in rtl8169_irq - remove array imr and isr - remove min_irq_nvecs and max_irq_nvecs, replaced with help function get_min_irq_nvecs and get_max_irq_nvecs - alloc irq by flags, instead of PCI_IRQ_ALL_TYPES drivers/net/ethernet/realtek/r8169_main.c | 161 +++++++++++++++++++--- 1 file changed, 144 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 791277e750ba..f02c4aa66b9d 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -77,6 +77,9 @@ #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) #define R8169_TX_STOP_THRS (MAX_SKB_FRAGS + 1) #define R8169_TX_START_THRS (2 * R8169_TX_STOP_THRS) +#define R8169_MAX_MSIX_VEC 32 +#define RTL_ISR_VER_DEFAULT 1 +#define RTL_ISR_VER_8127 6 #define OCP_STD_PHY_BASE 0xa400 @@ -435,6 +438,8 @@ enum rtl8125_registers { #define INT_CFG0_CLKREQEN BIT(3) IntrMask_8125 = 0x38, IntrStatus_8125 = 0x3c, + INTR_VEC_MAP_MASK = 0x800, + INTR_VEC_MAP_STATUS = 0x802, INT_CFG1_8125 = 0x7a, LEDSEL2 = 0x84, LEDSEL1 = 0x86, @@ -728,6 +733,15 @@ enum rtl_dash_type { RTL_DASH_25_BP, }; +struct rtl8169_napi { + struct napi_struct napi; + void *priv; +}; + +struct rtl8169_irq { + irq_handler_t handler; + unsigned int vector; +}; struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; @@ -745,9 +759,17 @@ struct rtl8169_private { dma_addr_t RxPhyAddr; struct page *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + struct rtl8169_irq irq_tbl[R8169_MAX_MSIX_VEC]; + struct rtl8169_napi r8169napi[R8169_MAX_MSIX_VEC]; + unsigned int num_rx_rings; u16 cp_cmd; u16 tx_lpi_timer; u32 irq_mask; + u16 hw_supp_num_rx_queues; + u8 hw_supp_isr_ver; + u8 hw_curr_isr_ver; + u8 irq_nvecs; + bool recheck_desc_ownbit; int irq; struct clk *clk; @@ -763,6 +785,8 @@ struct rtl8169_private { unsigned aspm_manageable:1; unsigned dash_enabled:1; bool sfp_mode:1; + bool rss_support:1; + bool rss_enable:1; dma_addr_t counters_phys_addr; struct rtl8169_counters *counters; struct rtl8169_tc_offsets tc_offset; @@ -2680,6 +2704,21 @@ static void rtl_hw_reset(struct rtl8169_private *tp) rtl_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); } +static void rtl_software_parameter_initialize(struct rtl8169_private *tp) +{ + tp->num_rx_rings = 1; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_80: + tp->hw_supp_isr_ver = RTL_ISR_VER_8127; + break; + default: + tp->hw_supp_isr_ver = RTL_ISR_VER_DEFAULT; + break; + } + tp->hw_curr_isr_ver = tp->hw_supp_isr_ver; +} + static void rtl_request_firmware(struct rtl8169_private *tp) { struct rtl_fw *rtl_fw; @@ -4266,9 +4305,21 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) netdev_reset_queue(tp->dev); } +static void rtl8169_napi_disable(struct rtl8169_private *tp) +{ + for (int i = 0; i < tp->irq_nvecs; i++) + napi_disable(&tp->r8169napi[i].napi); +} + +static void rtl8169_napi_enable(struct rtl8169_private *tp) +{ + for (int i = 0; i < tp->irq_nvecs; i++) + napi_enable(&tp->r8169napi[i].napi); +} + static void rtl8169_cleanup(struct rtl8169_private *tp) { - napi_disable(&tp->napi); + rtl8169_napi_disable(tp); /* Give a racing hard_start_xmit a few cycles to complete. */ synchronize_net(); @@ -4314,7 +4365,7 @@ static void rtl_reset_work(struct rtl8169_private *tp) for (i = 0; i < NUM_RX_DESC; i++) rtl8169_mark_to_asic(tp->RxDescArray + i); - napi_enable(&tp->napi); + rtl8169_napi_enable(tp); rtl_hw_start(tp); } @@ -4820,7 +4871,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, int budget goto release_descriptor; } - skb = napi_alloc_skb(&tp->napi, pkt_size); + skb = napi_alloc_skb(&tp->r8169napi[0].napi, pkt_size); if (unlikely(!skb)) { dev->stats.rx_dropped++; goto release_descriptor; @@ -4844,7 +4895,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, int budget if (skb->pkt_type == PACKET_MULTICAST) dev->stats.multicast++; - napi_gro_receive(&tp->napi, skb); + napi_gro_receive(&tp->r8169napi[0].napi, skb); dev_sw_netstats_rx_add(dev, pkt_size); release_descriptor: @@ -4856,7 +4907,8 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, int budget static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { - struct rtl8169_private *tp = dev_instance; + struct rtl8169_napi *napi = dev_instance; + struct rtl8169_private *tp = napi->priv; u32 status = rtl_get_events(tp); if ((status & 0xffff) == 0xffff || !(status & tp->irq_mask)) @@ -4873,13 +4925,46 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) phy_mac_interrupt(tp->phydev); rtl_irq_disable(tp); - napi_schedule(&tp->napi); + napi_schedule(&napi->napi); out: rtl_ack_events(tp, status); return IRQ_HANDLED; } +static void rtl8169_free_irq(struct rtl8169_private *tp) +{ + for (int i = 0; i < tp->irq_nvecs; i++) { + struct rtl8169_napi *napi = &tp->r8169napi[i]; + + pci_free_irq(tp->pci_dev, i, napi); + } +} + +static int rtl8169_request_irq(struct rtl8169_private *tp) +{ + struct net_device *dev = tp->dev; + struct rtl8169_napi *napi; + struct rtl8169_irq *irq; + int rc = 0; + + for (int i = 0; i < tp->irq_nvecs; i++) { + irq = &tp->irq_tbl[i]; + napi = &tp->r8169napi[i]; + irq->handler = rtl8169_interrupt; + rc = pci_request_irq(tp->pci_dev, i, irq->handler, + NULL, napi, "%s-%d", dev->name, i); + if (rc) + break; + + irq->vector = pci_irq_vector(tp->pci_dev, i); + } + + if (rc) + rtl8169_free_irq(tp); + return rc; +} + static void rtl_task(struct work_struct *work) { struct rtl8169_private *tp = @@ -4914,9 +4999,10 @@ static void rtl_task(struct work_struct *work) static int rtl8169_poll(struct napi_struct *napi, int budget) { - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); + struct rtl8169_napi *r8169_napi = container_of(napi, struct rtl8169_napi, napi); + struct rtl8169_private *tp = r8169_napi->priv; struct net_device *dev = tp->dev; - int work_done; + int work_done = 0; rtl_tx(dev, tp, budget); @@ -5035,7 +5121,7 @@ static void rtl8169_up(struct rtl8169_private *tp) phy_init_hw(tp->phydev); phy_resume(tp->phydev); rtl8169_init_phy(tp); - napi_enable(&tp->napi); + rtl8169_napi_enable(tp); enable_work(&tp->wk.work); rtl_reset_work(tp); @@ -5053,7 +5139,7 @@ static int rtl8169_close(struct net_device *dev) rtl8169_down(tp); rtl8169_rx_clear(tp); - free_irq(tp->irq, tp); + rtl8169_free_irq(tp); phy_disconnect(tp->phydev); @@ -5082,7 +5168,6 @@ static int rtl_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; - unsigned long irqflags; int retval = -ENOMEM; pm_runtime_get_sync(&pdev->dev); @@ -5107,8 +5192,7 @@ static int rtl_open(struct net_device *dev) rtl_request_firmware(tp); - irqflags = pci_dev_msi_enabled(pdev) ? IRQF_NO_THREAD : IRQF_SHARED; - retval = request_irq(tp->irq, rtl8169_interrupt, irqflags, dev->name, tp); + retval = rtl8169_request_irq(tp); if (retval < 0) goto err_release_fw_2; @@ -5125,7 +5209,7 @@ static int rtl_open(struct net_device *dev) return retval; err_free_irq: - free_irq(tp->irq, tp); + rtl8169_free_irq(tp); err_release_fw_2: rtl_release_firmware(tp); rtl8169_rx_clear(tp); @@ -5328,7 +5412,9 @@ static void rtl_set_irq_mask(struct rtl8169_private *tp) static int rtl_alloc_irq(struct rtl8169_private *tp) { + struct pci_dev *pdev = tp->pci_dev; unsigned int flags; + int nvecs; switch (tp->mac_version) { case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: @@ -5344,7 +5430,15 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) break; } - return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags); + nvecs = pci_alloc_irq_vectors(pdev, 1, 1, flags); + + if (nvecs < 0) + return nvecs; + + tp->irq = pci_irq_vector(pdev, 0); + tp->irq_nvecs = nvecs; + + return 0; } static void rtl_read_mac_address(struct rtl8169_private *tp, @@ -5539,6 +5633,17 @@ static void rtl_hw_initialize(struct rtl8169_private *tp) } } +static int rtl8169_set_real_num_queue(struct rtl8169_private *tp) +{ + int retval; + + retval = netif_set_real_num_tx_queues(tp->dev, 1); + if (retval < 0) + return retval; + + return netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); +} + static int rtl_jumbo_max(struct rtl8169_private *tp) { /* Non-GBit versions don't support jumbo frames */ @@ -5599,6 +5704,18 @@ static bool rtl_aspm_is_safe(struct rtl8169_private *tp) return false; } +static void r8169_init_napi(struct rtl8169_private *tp) +{ + for (int i = 0; i < tp->irq_nvecs; i++) { + struct rtl8169_napi *r8169napi = &tp->r8169napi[i]; + int (*poll)(struct napi_struct *napi, int budget); + + poll = rtl8169_poll; + netif_napi_add(tp->dev, &r8169napi->napi, poll); + r8169napi->priv = tp; + } +} + static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct rtl_chip_info *chip; @@ -5703,11 +5820,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_hw_reset(tp); + rtl_software_parameter_initialize(tp); + rc = rtl_alloc_irq(tp); if (rc < 0) return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n"); - tp->irq = pci_irq_vector(pdev, 0); INIT_WORK(&tp->wk.work, rtl_task); disable_work(&tp->wk.work); @@ -5716,7 +5834,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->ethtool_ops = &rtl8169_ethtool_ops; - netif_napi_add(dev, &tp->napi, rtl8169_poll); + if (!tp->rss_support) { + netif_napi_add(dev, &tp->r8169napi[0].napi, rtl8169_poll); + tp->r8169napi[0].priv = tp; + } else { + r8169_init_napi(tp); + } dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; @@ -5778,6 +5901,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (jumbo_max) dev->max_mtu = jumbo_max; + rc = rtl8169_set_real_num_queue(tp); + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "set tx/rx num failure\n"); + rtl_set_irq_mask(tp); tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters), -- 2.43.0