From nobody Tue Jun 16 12:47:53 2026 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 05D5137756A; Mon, 20 Apr 2026 02:20:55 +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=1776651657; cv=none; b=C+BIv1HaQ+h7Nf4f+wrBFCSf8I0BF+0hyKG2A5ZMKlvxptBXZwBO70cBLTgUdOl840NnFn3Qx3TEVmgd7YbGQSRtPxea9qIZOn1nBQEBJxPKc+VW7Rt9wAx+/yNEeGFgGGC8f5AjHW3fUP66Wn/3rLjlK/wMT56ouwuUEvfLdmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651657; c=relaxed/simple; bh=ZCbuWCU9tV6IXABfR7T1+jJdUjBYDvr6VjklhOb8cR0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jpAA0B1+oS+hVNLujg+TURKuPuqIH/swo97QdH9lyjdy/k+bUlpvDF0vsTAO9BAEM6etDeVRWU2/F021mI/Pb2Se66MBuSprTv6FhMcA9sVjAKGMsWc+b5OjUg60v+V4HmJS5M3XLnhNi8HEhAx1nrEgBHyZK4SkBzcrult/G60= 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=Aew8x1qM; 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="Aew8x1qM" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KD560277428, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651614; bh=e+6zQgOXz/3PJlvNg67wi3PeQJQNEhCuhjSnQd8juio=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=Aew8x1qMDa2Nq6QaYBxd3VdlQaKOAFA4N7my6szS+L4smv34R1n3wj714qNan795P aGe/h+IzbHdSycUTdN/anUh8Kw2ldQyIWeVLNMikqP7UII36uF7Ai4+FTQurm5/o7y 5e9AQfErwK7JSyWfeJ1Ku6qZOtzGZcod6+96fvO8CnjdY008wuWgxsgx++mKYKBY1m SBMqPG3BgE6f262ZhvvNAvYva9ahDdOqFvG7DkWaOdoMvZrhqp8QBu6yl8uDvHeQbk fBl43OAugS78fh46GsKMsbgteACpIyCWR/zdSRMFGH+1wMDysScdXgitDXOKGZ8jP6 4b2TZBYe+d8SQ== Received: from RS-EX-MBS1.realsil.com.cn ([172.29.17.101]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KD560277428 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:13 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) 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.1748.39; Mon, 20 Apr 2026 10:20:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:13 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 1/9] r8169: add some register definitions Date: Mon, 20 Apr 2026 10:19:49 +0800 Message-ID: <20260420021957.1756-2-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu To support rss, this patch adds some macro definitions and register definitions. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 75 +++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 791277e750ba..0fbec27e4a0d 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -77,6 +77,23 @@ #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_RX_QUEUES 8 +#define R8169_MAX_TX_QUEUES 1 +#define R8169_MAX_MSIX_VEC 32 +#define R8127_MAX_TX_QUEUES 1 +#define R8127_MAX_RX_QUEUES 8 +#define R8127_MAX_IRQ 32 +#define R8127_MIN_IRQ 30 +#define RTL8127_RSS_KEY_SIZE 40 +#define RSS_CPU_NUM_OFFSET 16 +#define RSS_MASK_BITS_OFFSET 8 +#define RTL8127_MAX_INDIRECTION_TABLE_ENTRIES 128 +#define RXS_8125B_RSS_UDP_V4 BIT(27) +#define RXS_8125_RSS_IPV4_V4 BIT(28) +#define RXS_8125_RSS_IPV6_V4 BIT(29) +#define RXS_8125_RSS_TCP_V4 BIT(30) +#define RTL8127_RXS_RSS_L3_TYPE_MASK_V4 (RXS_8125_RSS_IPV4_V4 | RXS_8125_R= SS_IPV6_V4) +#define RTL8127_RXS_RSS_L4_TYPE_MASK_V4 (RXS_8125_RSS_TCP_V4 | RXS_8125B_R= SS_UDP_V4) =20 #define OCP_STD_PHY_BASE 0xa400 =20 @@ -435,6 +452,8 @@ enum rtl8125_registers { #define INT_CFG0_CLKREQEN BIT(3) IntrMask_8125 =3D 0x38, IntrStatus_8125 =3D 0x3c, + IntrMask1_8125 =3D 0x800, + IntrStatus1_8125 =3D 0x802, INT_CFG1_8125 =3D 0x7a, LEDSEL2 =3D 0x84, LEDSEL1 =3D 0x86, @@ -444,6 +463,36 @@ enum rtl8125_registers { RSS_CTRL_8125 =3D 0x4500, Q_NUM_CTRL_8125 =3D 0x4800, EEE_TXIDLE_TIMER_8125 =3D 0x6048, + TNPDS_Q1_LOW =3D 0x2100, + RDSAR_Q1_LOW =3D 0x4000, + IMR_V2_SET_REG_8125 =3D 0x0d0c, + IMR_V2_CLEAR_REG_8125 =3D 0x0d00, + IMR_V4_L2_CLEAR_REG_8125 =3D 0x0d10, + ISR_V2_8125 =3D 0x0d04, + ISR_V4_L2_8125 =3D 0x0d14, +}; + +enum rtl8127_msix_id { + MSIX_ID_V4_LINKCHG =3D 29, +}; + +enum rtl8127_rss_register_content { + RSS_CTRL_TCP_IPV4_SUPP =3D (1 << 0), + RSS_CTRL_IPV4_SUPP =3D (1 << 1), + RSS_CTRL_TCP_IPV6_SUPP =3D (1 << 2), + RSS_CTRL_IPV6_SUPP =3D (1 << 3), + RSS_CTRL_IPV6_EXT_SUPP =3D (1 << 4), + RSS_CTRL_TCP_IPV6_EXT_SUPP =3D (1 << 5), + RSS_CTRL_UDP_IPV4_SUPP =3D (1 << 11), + RSS_CTRL_UDP_IPV6_SUPP =3D (1 << 12), + RSS_CTRL_UDP_IPV6_EXT_SUPP =3D (1 << 13), + RSS_INDIRECTION_TBL_8125_V2 =3D 0x4700, + RSS_KEY_8125 =3D 0x4600, +}; + +enum rtl8127_rss_flag { + RTL_8125_RSS_FLAG_HASH_UDP_IPV4 =3D (1 << 0), + RTL_8125_RSS_FLAG_HASH_UDP_IPV6 =3D (1 << 1), }; =20 #define LEDSEL_MASK_8125 0x23f @@ -474,6 +523,10 @@ enum rtl_register_content { RxRUNT =3D (1 << 20), RxCRC =3D (1 << 19), =20 + RxRES_RSS =3D (1 << 22), + RxRUNT_RSS =3D (1 << 21), + RxCRC_RSS =3D (1 << 20), + /* ChipCmdBits */ StopReq =3D 0x80, CmdReset =3D 0x10, @@ -576,6 +629,9 @@ enum rtl_register_content { =20 /* magic enable v2 */ MagicPacket_v2 =3D (1 << 16), /* Wake up when receives a Magic Packet */ + ISRIMR_V6_LINKCHG =3D (1 << 29), + ISRIMR_V6_TOK_Q0 =3D (1 << 8), + ISRIMR_V6_ROK_Q0 =3D (1 << 0), }; =20 enum rtl_desc_bit { @@ -633,6 +689,11 @@ enum rtl_rx_desc_bit { #define RxProtoIP (PID1 | PID0) #define RxProtoMask RxProtoIP =20 + RxUDPT_v4 =3D (1 << 19), + RxTCPT_v4 =3D (1 << 18), + RxUDPF_v4 =3D (1 << 16), /* UDP/IP checksum failed */ + RxTCPF_v4 =3D (1 << 15), /* TCP/IP checksum failed */ + IPFail =3D (1 << 16), /* IP checksum failed */ UDPFail =3D (1 << 15), /* UDP/IP checksum failed */ TCPFail =3D (1 << 14), /* TCP/IP checksum failed */ @@ -659,6 +720,11 @@ struct RxDesc { __le64 addr; }; =20 +enum features { + RTL_FEATURE_MSI =3D (1 << 1), + RTL_FEATURE_MSIX =3D (1 << 2), +}; + struct ring_info { struct sk_buff *skb; u32 len; @@ -728,6 +794,13 @@ enum rtl_dash_type { RTL_DASH_25_BP, }; =20 +enum rx_desc_ring_type { + RX_DESC_RING_TYPE_UNKNOWN =3D 0, + RX_DESC_RING_TYPE_DEAFULT, + RX_DESC_RING_TYPE_RSS, + RX_DESC_RING_TYPE_MAX +}; + struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; @@ -763,6 +836,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; --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 CFAD2377034; Mon, 20 Apr 2026 02:20:55 +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=1776651658; cv=none; b=PB8P7ot6kOfYIliqHZywSqrxQUvBurAv8dqbNTS9N20WesoBk7XkxHefuMAOgZVj606f72xAexDOMDw8gT7310swu7pvV4zv62ndFrBpTlqOIYd+diOaWnMt7S/Ci+DD6Va/5gRqkFAM6nnmR76u8w95WQ2FLEstW7JWyFS+LoM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651658; c=relaxed/simple; bh=671bt8nxwLW6ipSgCW3y2pQ5kvoYvqyOkwecJoSwST8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dIljwCinoLXx7Vj897EaRSH5znbjIw2zFEcaZkMUtM9ahZ4KqWHLWIyHObUKbqJv+BF1hw4cOyP1mplxSR0HMsMJIfEOOqp9L+B0rjJTmbtDkGy5nKWfvJxUFXCO1kQPXdMN3sGRtpG1/jZQty5uRzHMcvq+9fx6HQz3/wccnvU= 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=uFzav8Ud; 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="uFzav8Ud" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KE540277428, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651614; bh=xcjah/iG3bssidlwXwaB0tyfED5Vk30TSK9W2S0+Cz4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=uFzav8UdRaSfVffsv96+fQ0JCnAoYHLZOhWUIPHj32P9BjtVxOoS9XMZRN723E32U 6WTlXl9PND3GP4RL4ZYF525LLO1YQRAkk5Y1BXZaD5AnUT7+xFddlzCx3uDoCWhDnm TfhqftJ4aKx3RZX34aHFnfYq8Gq3a0MqTgKIfPHo9zTe73xTvDGJateeuAO3UCOija ejMBvdtmUuOJAoIGX25dpfFdm75migufNXhHuqNR78i+BnSeAuik8SwJnlyFmpGEIz /VJ3R9eBK4iZqGO3NRd2LmzBLEVNPiQIYIO2qJtupW5RZD/2DUnLIboe+nSysRdatM 3FgWqKAawbvgA== Received: from RS-EX-MBS1.realsil.com.cn ([172.29.17.101]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KE540277428 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:14 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) 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.1748.39; Mon, 20 Apr 2026 10:20:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:13 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 2/9] r8169: add napi and irq support Date: Mon, 20 Apr 2026 10:19:50 +0800 Message-ID: <20260420021957.1756-3-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu Multi tx queues and rx queues require multi irq support. Each irq pairs with one napi. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 205 ++++++++++++++++++++-- 1 file changed, 187 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 0fbec27e4a0d..d1f3a208bd1b 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -794,6 +794,19 @@ enum rtl_dash_type { RTL_DASH_25_BP, }; =20 +struct rtl8169_napi { + struct napi_struct napi; + void *priv; + int index; +}; + +struct rtl8169_irq { + irq_handler_t handler; + unsigned int vector; + u8 requested; + char name[IFNAMSIZ + 10]; +}; + enum rx_desc_ring_type { RX_DESC_RING_TYPE_UNKNOWN =3D 0, RX_DESC_RING_TYPE_DEAFULT, @@ -818,9 +831,20 @@ 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]; + u16 isr_reg[R8169_MAX_MSIX_VEC]; + u16 imr_reg[R8169_MAX_MSIX_VEC]; + unsigned int num_tx_rings; + unsigned int num_rx_rings; u16 cp_cmd; u16 tx_lpi_timer; u32 irq_mask; + u8 min_irq_nvecs; + u8 max_irq_nvecs; + u8 HwSuppIsrVer; + u8 HwCurrIsrVer; + u8 irq_nvecs; int irq; struct clk *clk; =20 @@ -2755,6 +2779,45 @@ static void rtl_hw_reset(struct rtl8169_private *tp) rtl_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); } =20 +static void rtl_setup_mqs_reg(struct rtl8169_private *tp) +{ + if (tp->mac_version <=3D RTL_GIGA_MAC_VER_52) { + tp->isr_reg[0] =3D IntrStatus; + tp->imr_reg[0] =3D IntrMask; + } else { + tp->isr_reg[0] =3D IntrStatus_8125; + tp->imr_reg[0] =3D IntrMask_8125; + } + + for (int i =3D 1; i < tp->max_irq_nvecs; i++) + tp->isr_reg[i] =3D (u16)(IntrStatus1_8125 + (i - 1) * 4); + + for (int i =3D 1; i < tp->max_irq_nvecs; i++) + tp->imr_reg[i] =3D (u16)(IntrMask1_8125 + (i - 1) * 4); +} + +static void rtl_software_parameter_initialize(struct rtl8169_private *tp) +{ + tp->num_rx_rings =3D 1; + tp->num_tx_rings =3D 1; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_80: + tp->min_irq_nvecs =3D R8127_MIN_IRQ; + tp->max_irq_nvecs =3D R8127_MAX_IRQ; + tp->HwSuppIsrVer =3D 6; + break; + default: + tp->min_irq_nvecs =3D 1; + tp->max_irq_nvecs =3D 1; + tp->HwSuppIsrVer =3D 1; + break; + } + tp->HwCurrIsrVer =3D tp->HwSuppIsrVer; + + rtl_setup_mqs_reg(tp); +} + static void rtl_request_firmware(struct rtl8169_private *tp) { struct rtl_fw *rtl_fw; @@ -4294,6 +4357,7 @@ static int rtl8169_rx_fill(struct rtl8169_private *tp) return 0; } =20 + static int rtl8169_init_ring(struct rtl8169_private *tp) { rtl8169_init_ring_indexes(tp); @@ -4313,6 +4377,7 @@ static void rtl8169_unmap_tx_skb(struct rtl8169_priva= te *tp, unsigned int entry) DMA_TO_DEVICE); memset(desc, 0, sizeof(*desc)); memset(tx_skb, 0, sizeof(*tx_skb)); + } =20 static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, @@ -4341,9 +4406,21 @@ static void rtl8169_tx_clear(struct rtl8169_private = *tp) netdev_reset_queue(tp->dev); } =20 +static void rtl8169_napi_disable(struct rtl8169_private *tp) +{ + for (int i =3D 0; i < tp->irq_nvecs; i++) + napi_disable(&tp->r8169napi[i].napi); +} + +static void rtl8169_napi_enable(struct rtl8169_private *tp) +{ + for (int i =3D 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); =20 /* Give a racing hard_start_xmit a few cycles to complete. */ synchronize_net(); @@ -4389,7 +4466,8 @@ static void rtl_reset_work(struct rtl8169_private *tp) for (i =3D 0; i < NUM_RX_DESC; i++) rtl8169_mark_to_asic(tp->RxDescArray + i); =20 - napi_enable(&tp->napi); + rtl8169_napi_enable(tp); + rtl_hw_start(tp); } =20 @@ -4895,7 +4973,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8= 169_private *tp, int budget goto release_descriptor; } =20 - skb =3D napi_alloc_skb(&tp->napi, pkt_size); + skb =3D napi_alloc_skb(&tp->r8169napi[0].napi, pkt_size); if (unlikely(!skb)) { dev->stats.rx_dropped++; goto release_descriptor; @@ -4919,7 +4997,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8= 169_private *tp, int budget if (skb->pkt_type =3D=3D PACKET_MULTICAST) dev->stats.multicast++; =20 - napi_gro_receive(&tp->napi, skb); + napi_gro_receive(&tp->r8169napi[0].napi, skb); =20 dev_sw_netstats_rx_add(dev, pkt_size); release_descriptor: @@ -4931,7 +5009,8 @@ static int rtl_rx(struct net_device *dev, struct rtl8= 169_private *tp, int budget =20 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { - struct rtl8169_private *tp =3D dev_instance; + struct rtl8169_napi *napi =3D dev_instance; + struct rtl8169_private *tp =3D napi->priv; u32 status =3D rtl_get_events(tp); =20 if ((status & 0xffff) =3D=3D 0xffff || !(status & tp->irq_mask)) @@ -4948,13 +5027,53 @@ static irqreturn_t rtl8169_interrupt(int irq, void = *dev_instance) phy_mac_interrupt(tp->phydev); =20 rtl_irq_disable(tp); - napi_schedule(&tp->napi); + napi_schedule(&napi->napi); out: rtl_ack_events(tp, status); =20 return IRQ_HANDLED; } =20 +static void rtl8169_free_irq(struct rtl8169_private *tp) +{ + for (int i =3D 0; i < tp->irq_nvecs; i++) { + struct rtl8169_irq *irq =3D &tp->irq_tbl[i]; + struct rtl8169_napi *napi =3D &tp->r8169napi[i]; + + if (irq->requested) { + irq->requested =3D 0; + pci_free_irq(tp->pci_dev, i, napi); + } + } +} + +static int rtl8169_request_irq(struct rtl8169_private *tp) +{ + struct net_device *dev =3D tp->dev; + int rc =3D 0; + struct rtl8169_irq *irq; + struct rtl8169_napi *napi; + const int len =3D sizeof(tp->irq_tbl[0].name); + + for (int i =3D 0; i < tp->irq_nvecs; i++) { + irq =3D &tp->irq_tbl[i]; + + napi =3D &tp->r8169napi[i]; + snprintf(irq->name, len, "%s-%d", dev->name, i); + rc =3D pci_request_irq(tp->pci_dev, i, rtl8169_interrupt, NULL, napi, ir= q->name); + + if (rc) + break; + + irq->vector =3D pci_irq_vector(tp->pci_dev, i); + irq->requested =3D 1; + } + + if (rc) + rtl8169_free_irq(tp); + return rc; +} + static void rtl_task(struct work_struct *work) { struct rtl8169_private *tp =3D @@ -4989,9 +5108,10 @@ static void rtl_task(struct work_struct *work) =20 static int rtl8169_poll(struct napi_struct *napi, int budget) { - struct rtl8169_private *tp =3D container_of(napi, struct rtl8169_private,= napi); + struct rtl8169_napi *r8169_napi =3D container_of(napi, struct rtl8169_nap= i, napi); + struct rtl8169_private *tp =3D r8169_napi->priv; struct net_device *dev =3D tp->dev; - int work_done; + int work_done =3D 0; =20 rtl_tx(dev, tp, budget); =20 @@ -5110,7 +5230,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); =20 @@ -5125,10 +5245,12 @@ static int rtl8169_close(struct net_device *dev) pm_runtime_get_sync(&pdev->dev); =20 netif_stop_queue(dev); + rtl8169_down(tp); rtl8169_rx_clear(tp); =20 - free_irq(tp->irq, tp); + + rtl8169_free_irq(tp); =20 phy_disconnect(tp->phydev); =20 @@ -5183,14 +5305,14 @@ static int rtl_open(struct net_device *dev) rtl_request_firmware(tp); =20 irqflags =3D pci_dev_msi_enabled(pdev) ? IRQF_NO_THREAD : IRQF_SHARED; - retval =3D request_irq(tp->irq, rtl8169_interrupt, irqflags, dev->name, t= p); + + retval =3D rtl8169_request_irq(tp); if (retval < 0) goto err_release_fw_2; =20 retval =3D r8169_phy_connect(tp); if (retval) goto err_free_irq; - rtl8169_up(tp); rtl8169_init_counter_offsets(tp); netif_start_queue(dev); @@ -5200,7 +5322,7 @@ static int rtl_open(struct net_device *dev) return retval; =20 err_free_irq: - free_irq(tp->irq, tp); + rtl8169_free_irq(tp); err_release_fw_2: rtl_release_firmware(tp); rtl8169_rx_clear(tp); @@ -5265,7 +5387,7 @@ static int rtl8169_runtime_resume(struct device *dev) rtl_rar_set(tp, tp->dev->dev_addr); __rtl8169_set_wol(tp, tp->saved_wolopts); =20 - if (tp->TxDescArray) + if (netif_running(tp->dev)) rtl8169_up(tp); =20 netif_device_attach(tp->dev); @@ -5303,7 +5425,7 @@ static int rtl8169_runtime_suspend(struct device *dev= ice) { struct rtl8169_private *tp =3D dev_get_drvdata(device); =20 - if (!tp->TxDescArray) { + if (!netif_running(tp->dev)) { netif_device_detach(tp->dev); return 0; } @@ -5403,7 +5525,9 @@ static void rtl_set_irq_mask(struct rtl8169_private *= tp) =20 static int rtl_alloc_irq(struct rtl8169_private *tp) { + struct pci_dev *pdev =3D tp->pci_dev; unsigned int flags; + int nvecs =3D 1; =20 switch (tp->mac_version) { case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: @@ -5419,7 +5543,15 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) break; } =20 - return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags); + nvecs =3D pci_alloc_irq_vectors(pdev, tp->min_irq_nvecs, tp->max_irq_nvec= s, flags); + + if (nvecs < 0) + nvecs =3D pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + + tp->irq =3D pdev->irq; + tp->irq_nvecs =3D 1; + + return nvecs; } =20 static void rtl_read_mac_address(struct rtl8169_private *tp, @@ -5614,6 +5746,18 @@ static void rtl_hw_initialize(struct rtl8169_private= *tp) } } =20 +static int rtl8169_set_real_num_queue(struct rtl8169_private *tp) +{ + int retval; + + retval =3D netif_set_real_num_tx_queues(tp->dev, tp->num_tx_rings); + if (retval < 0) + return retval; + + retval =3D netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); + return retval; +} + static int rtl_jumbo_max(struct rtl8169_private *tp) { /* Non-GBit versions don't support jumbo frames */ @@ -5674,6 +5818,20 @@ static bool rtl_aspm_is_safe(struct rtl8169_private = *tp) return false; } =20 + +static void r8169_init_napi(struct rtl8169_private *tp) +{ + for (int i =3D 0; i < tp->irq_nvecs; i++) { + struct rtl8169_napi *r8169napi =3D &tp->r8169napi[i]; + int (*poll)(struct napi_struct *napi, int budget); + + poll =3D rtl8169_poll; + netif_napi_add(tp->dev, &r8169napi->napi, poll); + r8169napi->priv =3D tp; + r8169napi->index =3D i; + } +} + static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *= ent) { const struct rtl_chip_info *chip; @@ -5778,11 +5936,12 @@ static int rtl_init_one(struct pci_dev *pdev, const= struct pci_device_id *ent) =20 rtl_hw_reset(tp); =20 + rtl_software_parameter_initialize(tp); + rc =3D rtl_alloc_irq(tp); if (rc < 0) return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n"); =20 - tp->irq =3D pci_irq_vector(pdev, 0); =20 INIT_WORK(&tp->wk.work, rtl_task); disable_work(&tp->wk.work); @@ -5791,7 +5950,13 @@ static int rtl_init_one(struct pci_dev *pdev, const = struct pci_device_id *ent) =20 dev->ethtool_ops =3D &rtl8169_ethtool_ops; =20 - 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 =3D tp; + tp->r8169napi[0].index =3D 0; + } else { + r8169_init_napi(tp); + } =20 dev->hw_features =3D NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; @@ -5853,6 +6018,10 @@ static int rtl_init_one(struct pci_dev *pdev, const = struct pci_device_id *ent) if (jumbo_max) dev->max_mtu =3D jumbo_max; =20 + rc =3D 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); =20 tp->counters =3D dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters), --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 232B1377578; Mon, 20 Apr 2026 02:20:55 +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=1776651659; cv=none; b=G6LGYXwlOZ29gmW7QRu/YGQoYfLYPfR9ISqEFioelQs/XM8bwzWBBOPiClA55BoxG4RdzrgZWG8YMJn06ooRtO7zK3RjzW8vJ03TPmvS2SWV9T/lfFMNe0CFwJscemayjG4mnpP7z48RWNIGnvfrqqjmczsj/+TigKvLpJUlYUg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651659; c=relaxed/simple; bh=vn6hjpycZXNuSGq4lvrMeKXhiAvathN5/3PhYZ529Pk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aBPmtTV8kXiSMNWUbxQiZ0B49bhDrD1v7yz6PTCyY9vBR4KL9ddpKIShy9ETaT9KZrj2TJY16C+DcU2MWXy84NVW4bn9xYOLSBg9jHB5ssA3Z4xwsH/QvS31oAD4Q2j3U0IjPryx7jVrwQE4NgF2XxOT4SxqVqTszliVL6x0QmQ= 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=kmFKTkdU; 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="kmFKTkdU" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KDBl8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651614; bh=h2GX1lW2lel+asORDWiJeK0QZqoe1ReFeJMfHQnb3zo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=kmFKTkdUu6EXa1YIhUvW/OxEGNqOyjoZqk4+yMhTRyEZi9R99toovFiMtdXR3FBUy 5g1aCnbYYkJYYUUAzW3Qfst/228P6V0xaLLVVs2WD9XNzciZxaebcJcyv55dN/QJ6S qTy1zOlvZtIfyTW+DNLBlouB2AVHSCQQW3qkkU3cv2Mr6mbDWSuZGSPsvlHDCamd8M r/OtXtK2AH66FZRxwRLP9DGdy1YoWaqgty+53H06adYYjIjAP1VtzsgoCovrpkuCtw 8php3R3XtVWgl/Lo4Oxj5CUe788tJuNr9NU91n04DiCzs+IoNBOWHdnr5cFE7d5uXh hz4IPMtqrp+EQ== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KDBl8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:14 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:13 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 3/9] r8169: add support for multi tx queues Date: Mon, 20 Apr 2026 10:19:51 +0800 Message-ID: <20260420021957.1756-4-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch support for multi tx queues. But we still use one tx queue here. More support will be available in rss support patch. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 278 ++++++++++++++++------ 1 file changed, 199 insertions(+), 79 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index d1f3a208bd1b..05f0cb532a31 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -73,7 +73,6 @@ #define R8169_RX_BUF_SIZE (SZ_16K - 1) #define NUM_TX_DESC 256 /* Number of Tx descriptor registers */ #define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #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) @@ -794,6 +793,18 @@ enum rtl_dash_type { RTL_DASH_25_BP, }; =20 +struct rtl8169_tx_ring { + u32 index; /* Tx queue index */ + u32 cur_tx; /* Index into the Tx descriptor buffer of next Tx pkt. */ + u32 dirty_tx; /* Index into the Tx descriptor buffer for recycling. */ + u32 num_tx_desc; /* num of Tx desc */ + struct TxDesc *TxDescArray; /* array of Rx Desc*/ + u32 TxDescAllocSize; /* memory size per descs of ring */ + dma_addr_t TxPhyAddr; /* Tx desc physical address */ + struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + u16 tdsar_reg; /* Transmit Descriptor Start Address */ +}; + struct rtl8169_napi { struct napi_struct napi; void *priv; @@ -823,16 +834,12 @@ struct rtl8169_private { enum mac_version mac_version; enum rtl_dash_type dash_type; u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; 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]; + struct rtl8169_tx_ring tx_ring[R8169_MAX_TX_QUEUES]; u16 isr_reg[R8169_MAX_MSIX_VEC]; u16 imr_reg[R8169_MAX_MSIX_VEC]; unsigned int num_tx_rings; @@ -840,11 +847,14 @@ struct rtl8169_private { u16 cp_cmd; u16 tx_lpi_timer; u32 irq_mask; + u16 HwSuppNumTxQueues; u8 min_irq_nvecs; u8 max_irq_nvecs; u8 HwSuppIsrVer; u8 HwCurrIsrVer; u8 irq_nvecs; + u8 recheck_desc_ownbit; + unsigned int features; int irq; struct clk *clk; =20 @@ -2718,9 +2728,28 @@ static void rtl_init_rxcfg(struct rtl8169_private *t= p) } } =20 +static void rtl8169_tx_desc_init(struct rtl8169_private *tp) +{ + for (int i =3D 0; i < tp->num_tx_rings; i++) { + struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; + + memset(ring->TxDescArray, 0x0, ring->TxDescAllocSize); + ring->TxDescArray[ring->num_tx_desc - 1].opts1 =3D cpu_to_le32(RingEnd); + } +} + static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) { - tp->dirty_tx =3D tp->cur_tx =3D tp->cur_rx =3D 0; + struct net_device *dev =3D tp->dev; + + for (int i =3D 0; i < tp->HwSuppNumTxQueues; i++) { + struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; + + ring->dirty_tx =3D 0; + ring->cur_tx =3D 0; + ring->index =3D i; + netdev_tx_reset_queue(netdev_get_tx_queue(dev, i)); + } } =20 static void rtl_jumbo_config(struct rtl8169_private *tp) @@ -2779,8 +2808,18 @@ static void rtl_hw_reset(struct rtl8169_private *tp) rtl_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); } =20 +static void rtl_set_ring_size(struct rtl8169_private *tp, u32 rx_num, u32 = tx_num) +{ + for (int i =3D 0; i < tp->HwSuppNumTxQueues; i++) + tp->tx_ring[i].num_tx_desc =3D tx_num; +} + static void rtl_setup_mqs_reg(struct rtl8169_private *tp) { + tp->tx_ring[0].tdsar_reg =3D TxDescStartAddrLow; + for (int i =3D 1; i < tp->HwSuppNumTxQueues; i++) + tp->tx_ring[i].tdsar_reg =3D (u16)(TNPDS_Q1_LOW + (i - 1) * 8); + if (tp->mac_version <=3D RTL_GIGA_MAC_VER_52) { tp->isr_reg[0] =3D IntrStatus; tp->imr_reg[0] =3D IntrMask; @@ -2805,17 +2844,20 @@ static void rtl_software_parameter_initialize(struc= t rtl8169_private *tp) case RTL_GIGA_MAC_VER_80: tp->min_irq_nvecs =3D R8127_MIN_IRQ; tp->max_irq_nvecs =3D R8127_MAX_IRQ; + tp->HwSuppNumTxQueues =3D R8127_MAX_TX_QUEUES; tp->HwSuppIsrVer =3D 6; break; default: tp->min_irq_nvecs =3D 1; tp->max_irq_nvecs =3D 1; + tp->HwSuppNumTxQueues =3D 1; tp->HwSuppIsrVer =3D 1; break; } tp->HwCurrIsrVer =3D tp->HwSuppIsrVer; =20 rtl_setup_mqs_reg(tp); + rtl_set_ring_size(tp, NUM_RX_DESC, NUM_TX_DESC); } =20 static void rtl_request_firmware(struct rtl8169_private *tp) @@ -2947,10 +2989,14 @@ static void rtl_set_rx_tx_desc_registers(struct rtl= 8169_private *tp) * register to be written before TxDescAddrLow to work. * Switching from MMIO to I/O access fixes the issue as well. */ - RTL_W32(tp, TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(tp, TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); + for (int i =3D 0; i < tp->num_tx_rings; i++) { + struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; + + RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); + RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); + } } =20 static void rtl8169_set_magic_reg(struct rtl8169_private *tp) @@ -4357,43 +4403,85 @@ static int rtl8169_rx_fill(struct rtl8169_private *= tp) return 0; } =20 +static int rtl8169_alloc_tx_desc(struct rtl8169_private *tp) +{ + struct rtl8169_tx_ring *ring; + struct pci_dev *pdev =3D tp->pci_dev; + + for (int i =3D 0; i < tp->num_tx_rings; i++) { + ring =3D &tp->tx_ring[i]; + ring->TxDescAllocSize =3D (ring->num_tx_desc + 1) * sizeof(struct TxDesc= ); + ring->TxDescArray =3D dma_alloc_coherent(&pdev->dev, + ring->TxDescAllocSize, + &ring->TxPhyAddr, + GFP_KERNEL); + if (!ring->TxDescArray) + return -ENOMEM; + } + return 0; +} + +static void rtl8169_free_tx_desc(struct rtl8169_private *tp) +{ + struct rtl8169_tx_ring *ring; + struct pci_dev *pdev =3D tp->pci_dev; + + for (int i =3D 0; i < tp->num_tx_rings; i++) { + ring =3D &tp->tx_ring[i]; + if (ring->TxDescArray) { + dma_free_coherent(&pdev->dev, + ring->TxDescAllocSize, + ring->TxDescArray, + ring->TxPhyAddr); + ring->TxDescArray =3D NULL; + } + } +} + =20 static int rtl8169_init_ring(struct rtl8169_private *tp) { + int retval =3D 0; + rtl8169_init_ring_indexes(tp); + rtl8169_tx_desc_init(tp); + + for (int i =3D 0; i < tp->num_tx_rings; i++) { + struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; + + memset(ring->tx_skb, 0x0, sizeof(ring->tx_skb)); + } + =20 - memset(tp->tx_skb, 0, sizeof(tp->tx_skb)); - memset(tp->Rx_databuff, 0, sizeof(tp->Rx_databuff)); =20 return rtl8169_rx_fill(tp); } =20 -static void rtl8169_unmap_tx_skb(struct rtl8169_private *tp, unsigned int = entry) +static void rtl8169_unmap_tx_skb(struct rtl8169_private *tp, + struct ring_info *tx_skb, + struct TxDesc *desc) { - struct ring_info *tx_skb =3D tp->tx_skb + entry; - struct TxDesc *desc =3D tp->TxDescArray + entry; + dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), tx_skb->len, DMA= _TO_DEVICE); =20 - dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), tx_skb->len, - DMA_TO_DEVICE); memset(desc, 0, sizeof(*desc)); memset(tx_skb, 0, sizeof(*tx_skb)); =20 } =20 -static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, - unsigned int n) +static void rtl8169_tx_clear_range(struct rtl8169_private *tp, struct rtl8= 169_tx_ring *ring, + u32 start, unsigned int n) { unsigned int i; =20 for (i =3D 0; i < n; i++) { - unsigned int entry =3D (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb =3D tp->tx_skb + entry; + unsigned int entry =3D (start + i) % ring->num_tx_desc; + struct ring_info *tx_skb =3D ring->tx_skb + entry; unsigned int len =3D tx_skb->len; =20 if (len) { struct sk_buff *skb =3D tx_skb->skb; =20 - rtl8169_unmap_tx_skb(tp, entry); + rtl8169_unmap_tx_skb(tp, tx_skb, ring->TxDescArray + entry); if (skb) dev_consume_skb_any(skb); } @@ -4402,7 +4490,13 @@ static void rtl8169_tx_clear_range(struct rtl8169_pr= ivate *tp, u32 start, =20 static void rtl8169_tx_clear(struct rtl8169_private *tp) { - rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); + for (int i =3D 0; i < tp->num_tx_rings; i++) { + struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; + + rtl8169_tx_clear_range(tp, ring, ring->dirty_tx, ring->num_tx_desc); + ring->cur_tx =3D 0; + ring->dirty_tx =3D 0; + } netdev_reset_queue(tp->dev); } =20 @@ -4478,10 +4572,15 @@ static void rtl8169_tx_timeout(struct net_device *d= ev, unsigned int txqueue) rtl_schedule_task(tp, RTL_FLAG_TASK_TX_TIMEOUT); } =20 -static int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32= len, - void *addr, unsigned int entry, bool desc_own) +static int rtl8169_tx_map(struct rtl8169_private *tp, + struct rtl8169_tx_ring *ring, + const u32 *opts, + u32 len, + void *addr, + unsigned int entry, + bool desc_own) { - struct TxDesc *txd =3D tp->TxDescArray + entry; + struct TxDesc *txd =3D ring->TxDescArray + entry; struct device *d =3D tp_to_dev(tp); dma_addr_t mapping; u32 opts1; @@ -4505,13 +4604,16 @@ static int rtl8169_tx_map(struct rtl8169_private *t= p, const u32 *opts, u32 len, opts1 |=3D DescOwn; txd->opts1 =3D cpu_to_le32(opts1); =20 - tp->tx_skb[entry].len =3D len; + ring->tx_skb[entry].len =3D len; =20 return 0; } =20 -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *= skb, - const u32 *opts, unsigned int entry) +static int rtl8169_xmit_frags(struct rtl8169_private *tp, + struct rtl8169_tx_ring *ring, + struct sk_buff *skb, + const u32 *opts, + unsigned int entry) { struct skb_shared_info *info =3D skb_shinfo(skb); unsigned int cur_frag; @@ -4523,14 +4625,14 @@ static int rtl8169_xmit_frags(struct rtl8169_privat= e *tp, struct sk_buff *skb, =20 entry =3D (entry + 1) % NUM_TX_DESC; =20 - if (unlikely(rtl8169_tx_map(tp, opts, len, addr, entry, true))) + if (unlikely(rtl8169_tx_map(tp, ring, opts, len, addr, entry, true))) goto err_out; } =20 return 0; =20 err_out: - rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); + rtl8169_tx_clear_range(tp, ring, ring->cur_tx + 1, cur_frag); return -EIO; } =20 @@ -4684,9 +4786,9 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_privat= e *tp, return true; } =20 -static unsigned int rtl_tx_slots_avail(struct rtl8169_private *tp) +static unsigned int rtl_tx_slots_avail(struct rtl8169_tx_ring *ring) { - return READ_ONCE(tp->dirty_tx) + NUM_TX_DESC - READ_ONCE(tp->cur_tx); + return READ_ONCE(ring->dirty_tx) + NUM_TX_DESC - READ_ONCE(ring->cur_tx); } =20 /* Versions RTL8102e and from RTL8168c onwards support csum_v2 */ @@ -4701,10 +4803,10 @@ static bool rtl_chip_supports_csum_v2(struct rtl816= 9_private *tp) } } =20 -static void rtl8169_doorbell(struct rtl8169_private *tp) +static void rtl8169_doorbell(struct rtl8169_private *tp, struct rtl8169_tx= _ring *ring) { if (rtl_is_8125(tp)) - RTL_W16(tp, TxPoll_8125, BIT(0)); + RTL_W16(tp, TxPoll_8125, BIT(ring->index)); else RTL_W8(tp, TxPoll, NPQ); } @@ -4713,16 +4815,18 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buf= f *skb, struct net_device *dev) { struct rtl8169_private *tp =3D netdev_priv(dev); - unsigned int entry =3D tp->cur_tx % NUM_TX_DESC; struct TxDesc *txd_first, *txd_last; bool stop_queue, door_bell; unsigned int frags; u32 opts[2]; + const u16 queue_mapping =3D skb_get_queue_mapping(skb); + struct rtl8169_tx_ring *ring =3D &tp->tx_ring[queue_mapping]; + unsigned int entry =3D ring->cur_tx % ring->num_tx_desc; =20 - if (unlikely(!rtl_tx_slots_avail(tp))) { + if (unlikely(!rtl_tx_slots_avail(ring))) { if (net_ratelimit()) netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); - netif_stop_queue(dev); + netif_stop_subqueue(dev, queue_mapping); return NETDEV_TX_BUSY; } =20 @@ -4734,47 +4838,49 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buf= f *skb, else if (!rtl8169_tso_csum_v2(tp, skb, opts)) goto err_dma_0; =20 - if (unlikely(rtl8169_tx_map(tp, opts, skb_headlen(skb), skb->data, + if (unlikely(rtl8169_tx_map(tp, ring, opts, skb_headlen(skb), skb->data, entry, false))) goto err_dma_0; =20 - txd_first =3D tp->TxDescArray + entry; + txd_first =3D ring->TxDescArray + entry; =20 frags =3D skb_shinfo(skb)->nr_frags; if (frags) { - if (rtl8169_xmit_frags(tp, skb, opts, entry)) + if (rtl8169_xmit_frags(tp, ring, skb, opts, entry)) goto err_dma_1; entry =3D (entry + frags) % NUM_TX_DESC; } =20 - txd_last =3D tp->TxDescArray + entry; + txd_last =3D ring->TxDescArray + entry; txd_last->opts1 |=3D cpu_to_le32(LastFrag); - tp->tx_skb[entry].skb =3D skb; + ring->tx_skb[entry].skb =3D skb; =20 skb_tx_timestamp(skb); =20 /* Force memory writes to complete before releasing descriptor */ dma_wmb(); =20 - door_bell =3D __netdev_sent_queue(dev, skb->len, netdev_xmit_more()); + struct netdev_queue *txq =3D netdev_get_tx_queue(dev, queue_mapping); + + door_bell =3D __netdev_tx_sent_queue(txq, skb->len, netdev_xmit_more()); =20 txd_first->opts1 |=3D cpu_to_le32(DescOwn | FirstFrag); =20 /* rtl_tx needs to see descriptor changes before updated tp->cur_tx */ smp_wmb(); =20 - WRITE_ONCE(tp->cur_tx, tp->cur_tx + frags + 1); + WRITE_ONCE(ring->cur_tx, ring->cur_tx + frags + 1); =20 - stop_queue =3D !netif_subqueue_maybe_stop(dev, 0, rtl_tx_slots_avail(tp), + stop_queue =3D !netif_subqueue_maybe_stop(dev, 0, rtl_tx_slots_avail(ring= ), R8169_TX_STOP_THRS, R8169_TX_START_THRS); if (door_bell || stop_queue) - rtl8169_doorbell(tp); + rtl8169_doorbell(tp, ring); =20 return NETDEV_TX_OK; =20 err_dma_1: - rtl8169_unmap_tx_skb(tp, entry); + rtl8169_unmap_tx_skb(tp, ring->tx_skb + entry, txd_first); err_dma_0: dev_kfree_skb_any(skb); dev->stats.tx_dropped++; @@ -4859,24 +4965,38 @@ static void rtl8169_pcierr_interrupt(struct net_dev= ice *dev) rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } =20 -static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp, - int budget) +static void rtl8169_desc_quirk(struct rtl8169_private *tp) +{ + RTL_R8(tp, tp->imr_reg[0]); +} + +static int rtl_tx(struct net_device *dev, struct rtl8169_private *tp, + struct rtl8169_tx_ring *ring, int budget) { unsigned int dirty_tx, bytes_compl =3D 0, pkts_compl =3D 0; struct sk_buff *skb; + u32 status; + unsigned int count =3D 0; + + dirty_tx =3D ring->dirty_tx; + + while (READ_ONCE(ring->cur_tx) !=3D dirty_tx) { + unsigned int entry =3D dirty_tx % ring->num_tx_desc; + struct ring_info *tx_skb =3D ring->tx_skb + entry; + + status =3D le32_to_cpu(READ_ONCE(ring->TxDescArray[entry].opts1)); + if (status & DescOwn) { + if (!tp->recheck_desc_ownbit) + break; + tp->recheck_desc_ownbit =3D false; + rtl8169_desc_quirk(tp); + status =3D le32_to_cpu(READ_ONCE(ring->TxDescArray[entry].opts1)); + if (status & DescOwn) + break; + } =20 - dirty_tx =3D tp->dirty_tx; - - while (READ_ONCE(tp->cur_tx) !=3D dirty_tx) { - unsigned int entry =3D dirty_tx % NUM_TX_DESC; - u32 status; - - status =3D le32_to_cpu(READ_ONCE(tp->TxDescArray[entry].opts1)); - if (status & DescOwn) - break; - - skb =3D tp->tx_skb[entry].skb; - rtl8169_unmap_tx_skb(tp, entry); + skb =3D tx_skb->skb; + rtl8169_unmap_tx_skb(tp, tx_skb, ring->TxDescArray + entry); =20 if (skb) { pkts_compl++; @@ -4886,12 +5006,13 @@ static void rtl_tx(struct net_device *dev, struct r= tl8169_private *tp, dirty_tx++; } =20 - if (tp->dirty_tx !=3D dirty_tx) { + if (ring->dirty_tx !=3D dirty_tx) { + count =3D dirty_tx - ring->dirty_tx; dev_sw_netstats_tx_add(dev, pkts_compl, bytes_compl); - WRITE_ONCE(tp->dirty_tx, dirty_tx); + WRITE_ONCE(ring->dirty_tx, dirty_tx); =20 netif_subqueue_completed_wake(dev, 0, pkts_compl, bytes_compl, - rtl_tx_slots_avail(tp), + rtl_tx_slots_avail(ring), R8169_TX_START_THRS); /* * 8168 hack: TxPoll requests are lost when the Tx packets are @@ -4901,9 +5022,10 @@ static void rtl_tx(struct net_device *dev, struct rt= l8169_private *tp, * If skb is NULL then we come here again once a tx irq is * triggered after the last fragment is marked transmitted. */ - if (READ_ONCE(tp->cur_tx) !=3D dirty_tx && skb) - rtl8169_doorbell(tp); + if (READ_ONCE(ring->cur_tx) !=3D dirty_tx && skb) + rtl8169_doorbell(tp, ring); } + return count; } =20 static inline int rtl8169_fragmented_frame(u32 status) @@ -5027,6 +5149,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *d= ev_instance) phy_mac_interrupt(tp->phydev); =20 rtl_irq_disable(tp); + tp->recheck_desc_ownbit =3D true; napi_schedule(&napi->napi); out: rtl_ack_events(tp, status); @@ -5113,7 +5236,8 @@ static int rtl8169_poll(struct napi_struct *napi, int= budget) struct net_device *dev =3D tp->dev; int work_done =3D 0; =20 - rtl_tx(dev, tp, budget); + for (int i =3D 0; i < tp->num_tx_rings; i++) + rtl_tx(dev, tp, &tp->tx_ring[i], budget); =20 work_done =3D rtl_rx(dev, tp, budget); =20 @@ -5256,10 +5380,8 @@ static int rtl8169_close(struct net_device *dev) =20 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray =3D NULL; tp->RxDescArray =3D NULL; + rtl8169_free_tx_desc(tp); =20 pm_runtime_put_sync(&pdev->dev); =20 @@ -5288,20 +5410,17 @@ static int rtl_open(struct net_device *dev) * Rx and Tx descriptors needs 256 bytes alignment. * dma_alloc_coherent provides more. */ - tp->TxDescArray =3D dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto out; =20 tp->RxDescArray =3D dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) + if (rtl8169_alloc_tx_desc(tp) < 0) goto err_free_tx_0; =20 retval =3D rtl8169_init_ring(tp); if (retval < 0) goto err_free_rx_1; =20 + rtl_request_firmware(tp); =20 irqflags =3D pci_dev_msi_enabled(pdev) ? IRQF_NO_THREAD : IRQF_SHARED; @@ -5331,9 +5450,7 @@ static int rtl_open(struct net_device *dev) tp->RxPhyAddr); tp->RxDescArray =3D NULL; err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray =3D NULL; + rtl8169_free_tx_desc(tp); goto out; } =20 @@ -5842,7 +5959,10 @@ static int rtl_init_one(struct pci_dev *pdev, const = struct pci_device_id *ent) u32 txconfig; u32 xid; =20 - dev =3D devm_alloc_etherdev(&pdev->dev, sizeof (*tp)); + dev =3D devm_alloc_etherdev_mqs(&pdev->dev, sizeof(*tp), + R8169_MAX_TX_QUEUES, + R8169_MAX_RX_QUEUES); + if (!dev) return -ENOMEM; =20 --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 96E96375AD0; Mon, 20 Apr 2026 02:20:55 +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=1776651658; cv=none; b=TIVFCsLJhJApk7ETiN9sdB77VBeH8o1hK4jbMcxh+REoq+VXqdu6wd1kGFWKoAHY8NWZbMxvywX6pO3qWUXCies39FFM6+MM3HZ9HufyUspg5Q0x9oTOEUM/2hTJrUb0GpPtnO8cUhYLWv8/PgzrncTajuApojFKOyW/5HZZGcU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651658; c=relaxed/simple; bh=qOd3bnZlFMcOjsJrn9PcHOdjbBuW+DQ7Q16HPRH/eGI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rev9Rtgoor3dnW7RyAqG2xkokwCPrIiBEvqp+Lw7aAwOCXDnJpliBPpngX5Hnr5qusISMQRMW5imUxFf2e/jRvyQHrbLRw9DZ+Ybp+r+DOrtm7zF8sRKmpJpjC47n8Juu1J0SkMGA5e6EUCLGhSmCJlWG+NVKG969dfWniFhlgE= 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=XEXFfFfn; 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="XEXFfFfn" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KEBm8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651614; bh=CjsHUf7itV/xdWKBobCkgIGE2i0tGSxJ60lvJ6uhGzU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=XEXFfFfn+TncDb77LOld1pa15tSX12WwdP8oFOgKLA8P/HEL8kiQt02rMlCvKDPxA P1jQbqSKTlok9s4zfrJecb3RLPeJAD2wX7QSoaONbZGKIiVFGIW5S8UtM5/ONWW7Nd EPr8EA0eBvuzzV66xW8bRxF8QXqzpBWQsh97P+VI0at4INU5JybAe5wxpFuTH8Sko1 zfYRsjgEMA34exdHshjwYK+r8WUFouEEdvO0bn95VJl54PEYmfurkqpyMsfOZWPIOb 0eqhAMJLl0qQj/oraH6eFXnZJ1TV00tC8BZ0n2PttaJr1etdwvS8Co3CIHZ5u9q5Ik 3mV0ej2czFZ3w== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KEBm8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:14 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:13 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:13 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 4/9] r8169: add support for multi rx queues Date: Mon, 20 Apr 2026 10:19:52 +0800 Message-ID: <20260420021957.1756-5-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch supports for multi rx queues. But we set rx queue num 1 here. We will add support for rx queue num 8 in rss patch. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 272 +++++++++++++++++----- 1 file changed, 212 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 05f0cb532a31..52e690eba644 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -73,7 +73,6 @@ #define R8169_RX_BUF_SIZE (SZ_16K - 1) #define NUM_TX_DESC 256 /* Number of Tx descriptor registers */ #define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#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_RX_QUEUES 8 @@ -793,6 +792,19 @@ enum rtl_dash_type { RTL_DASH_25_BP, }; =20 +struct rtl8169_rx_ring { + u32 index; /* Rx queue index */ + u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + u32 dirty_rx; /* Index into the Rx descriptor buffer for recycling. */ + u32 num_rx_desc; /* num of Rx desc */ + struct RxDesc *RxDescArray; /* array of Rx Desc*/ + u32 RxDescAllocSize; /* memory size per descs of ring */ + dma_addr_t RxDescPhyAddr[NUM_RX_DESC]; /* Rx data buffer physical dma add= ress */ + dma_addr_t RxPhyAddr; /* Rx desc physical address */ + struct page *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ + u16 rdsar_reg; /* Receive Descriptor Start Address */ +}; + struct rtl8169_tx_ring { u32 index; /* Tx queue index */ u32 cur_tx; /* Index into the Tx descriptor buffer of next Tx pkt. */ @@ -833,12 +845,9 @@ struct rtl8169_private { struct napi_struct napi; enum mac_version mac_version; enum rtl_dash_type dash_type; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t RxPhyAddr; - struct page *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ struct rtl8169_irq irq_tbl[R8169_MAX_MSIX_VEC]; struct rtl8169_napi r8169napi[R8169_MAX_MSIX_VEC]; + struct rtl8169_rx_ring rx_ring[R8169_MAX_RX_QUEUES]; struct rtl8169_tx_ring tx_ring[R8169_MAX_TX_QUEUES]; u16 isr_reg[R8169_MAX_MSIX_VEC]; u16 imr_reg[R8169_MAX_MSIX_VEC]; @@ -848,11 +857,13 @@ struct rtl8169_private { u16 tx_lpi_timer; u32 irq_mask; u16 HwSuppNumTxQueues; + u16 HwSuppNumRxQueues; u8 min_irq_nvecs; u8 max_irq_nvecs; u8 HwSuppIsrVer; u8 HwCurrIsrVer; u8 irq_nvecs; + u8 InitRxDescType; u8 recheck_desc_ownbit; unsigned int features; int irq; @@ -2728,6 +2739,15 @@ static void rtl_init_rxcfg(struct rtl8169_private *t= p) } } =20 +static void rtl8169_rx_desc_init(struct rtl8169_private *tp) +{ + for (int i =3D 0; i < tp->num_rx_rings; i++) { + struct rtl8169_rx_ring *ring =3D &tp->rx_ring[i]; + + memset(ring->RxDescArray, 0x0, ring->RxDescAllocSize); + } +} + static void rtl8169_tx_desc_init(struct rtl8169_private *tp) { for (int i =3D 0; i < tp->num_tx_rings; i++) { @@ -2750,6 +2770,14 @@ static void rtl8169_init_ring_indexes(struct rtl8169= _private *tp) ring->index =3D i; netdev_tx_reset_queue(netdev_get_tx_queue(dev, i)); } + + for (int i =3D 0; i < tp->HwSuppNumRxQueues; i++) { + struct rtl8169_rx_ring *ring =3D &tp->rx_ring[i]; + + ring->dirty_rx =3D 0; + ring->cur_rx =3D 0; + ring->index =3D i; + } } =20 static void rtl_jumbo_config(struct rtl8169_private *tp) @@ -2810,6 +2838,9 @@ static void rtl_hw_reset(struct rtl8169_private *tp) =20 static void rtl_set_ring_size(struct rtl8169_private *tp, u32 rx_num, u32 = tx_num) { + for (int i =3D 0; i < tp->HwSuppNumRxQueues; i++) + tp->rx_ring[i].num_rx_desc =3D rx_num; + for (int i =3D 0; i < tp->HwSuppNumTxQueues; i++) tp->tx_ring[i].num_tx_desc =3D tx_num; } @@ -2820,6 +2851,10 @@ static void rtl_setup_mqs_reg(struct rtl8169_private= *tp) for (int i =3D 1; i < tp->HwSuppNumTxQueues; i++) tp->tx_ring[i].tdsar_reg =3D (u16)(TNPDS_Q1_LOW + (i - 1) * 8); =20 + tp->rx_ring[0].rdsar_reg =3D RxDescAddrLow; + for (int i =3D 1; i < tp->HwSuppNumRxQueues; i++) + tp->rx_ring[i].rdsar_reg =3D (u16)(RDSAR_Q1_LOW + (i - 1) * 8); + if (tp->mac_version <=3D RTL_GIGA_MAC_VER_52) { tp->isr_reg[0] =3D IntrStatus; tp->imr_reg[0] =3D IntrMask; @@ -2845,15 +2880,18 @@ static void rtl_software_parameter_initialize(struc= t rtl8169_private *tp) tp->min_irq_nvecs =3D R8127_MIN_IRQ; tp->max_irq_nvecs =3D R8127_MAX_IRQ; tp->HwSuppNumTxQueues =3D R8127_MAX_TX_QUEUES; + tp->HwSuppNumRxQueues =3D R8127_MAX_RX_QUEUES; tp->HwSuppIsrVer =3D 6; break; default: tp->min_irq_nvecs =3D 1; tp->max_irq_nvecs =3D 1; tp->HwSuppNumTxQueues =3D 1; + tp->HwSuppNumRxQueues =3D 1; tp->HwSuppIsrVer =3D 1; break; } + tp->InitRxDescType =3D RX_DESC_RING_TYPE_DEAFULT; tp->HwCurrIsrVer =3D tp->HwSuppIsrVer; =20 rtl_setup_mqs_reg(tp); @@ -2989,14 +3027,18 @@ static void rtl_set_rx_tx_desc_registers(struct rtl= 8169_private *tp) * register to be written before TxDescAddrLow to work. * Switching from MMIO to I/O access fixes the issue as well. */ - RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); for (int i =3D 0; i < tp->num_tx_rings; i++) { struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; =20 RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); } + for (int i =3D 0; i < tp->num_rx_rings; i++) { + struct rtl8169_rx_ring *ring =3D &tp->rx_ring[i]; + + RTL_W32(tp, ring->rdsar_reg, ((u64)ring->RxPhyAddr) & DMA_BIT_MASK(32)); + RTL_W32(tp, ring->rdsar_reg + 4, ((u64)ring->RxPhyAddr >> 32)); + } } =20 static void rtl8169_set_magic_reg(struct rtl8169_private *tp) @@ -4332,7 +4374,7 @@ static int rtl8169_change_mtu(struct net_device *dev,= int new_mtu) return 0; } =20 -static void rtl8169_mark_to_asic(struct RxDesc *desc) +static void rtl8169_mark_to_asic_default(struct RxDesc *desc) { u32 eor =3D le32_to_cpu(desc->opts1) & RingEnd; =20 @@ -4342,13 +4384,19 @@ static void rtl8169_mark_to_asic(struct RxDesc *des= c) WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE)); } =20 +static void rtl8169_mark_to_asic(struct rtl8169_private *tp, struct RxDesc= *desc) +{ + rtl8169_mark_to_asic_default(desc); +} + static struct page *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) + struct rtl8169_rx_ring *ring, unsigned int index) { struct device *d =3D tp_to_dev(tp); int node =3D dev_to_node(d); dma_addr_t mapping; struct page *data; + struct RxDesc *desc =3D ring->RxDescArray + index; =20 data =3D alloc_pages_node(node, GFP_KERNEL, get_order(R8169_RX_BUF_SIZE)); if (!data) @@ -4361,44 +4409,56 @@ static struct page *rtl8169_alloc_rx_data(struct rt= l8169_private *tp, return NULL; } =20 + ring->RxDescPhyAddr[index] =3D mapping; desc->addr =3D cpu_to_le64(mapping); - rtl8169_mark_to_asic(desc); + rtl8169_mark_to_asic(tp, desc); =20 return data; } =20 -static void rtl8169_rx_clear(struct rtl8169_private *tp) +static void rtl8169_rx_clear(struct rtl8169_private *tp, struct rtl8169_rx= _ring *ring) { int i; =20 - for (i =3D 0; i < NUM_RX_DESC && tp->Rx_databuff[i]; i++) { + for (i =3D 0; i < NUM_RX_DESC && ring->Rx_databuff[i]; i++) { dma_unmap_page(tp_to_dev(tp), - le64_to_cpu(tp->RxDescArray[i].addr), + ring->RxDescPhyAddr[i], R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); - __free_pages(tp->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE)); - tp->Rx_databuff[i] =3D NULL; - tp->RxDescArray[i].addr =3D 0; - tp->RxDescArray[i].opts1 =3D 0; + __free_pages(ring->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE)); + ring->Rx_databuff[i] =3D NULL; + ring->RxDescPhyAddr[i] =3D 0; + ring->RxDescArray[i].addr =3D 0; + ring->RxDescArray[i].opts1 =3D 0; } } =20 -static int rtl8169_rx_fill(struct rtl8169_private *tp) +static void rtl8169_mark_as_last_descriptor_default(struct RxDesc *desc) +{ + desc->opts1 |=3D cpu_to_le32(RingEnd); +} + +static void rtl8169_mark_as_last_descriptor(struct rtl8169_private *tp, st= ruct RxDesc *desc) +{ + rtl8169_mark_as_last_descriptor_default(desc); +} + +static int rtl8169_rx_fill(struct rtl8169_private *tp, struct rtl8169_rx_r= ing *ring) { int i; =20 for (i =3D 0; i < NUM_RX_DESC; i++) { struct page *data; =20 - data =3D rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); + data =3D rtl8169_alloc_rx_data(tp, ring, i); if (!data) { - rtl8169_rx_clear(tp); + rtl8169_rx_clear(tp, ring); return -ENOMEM; } - tp->Rx_databuff[i] =3D data; + ring->Rx_databuff[i] =3D data; } =20 /* mark as last descriptor in the ring */ - tp->RxDescArray[NUM_RX_DESC - 1].opts1 |=3D cpu_to_le32(RingEnd); + rtl8169_mark_as_last_descriptor(tp, &ring->RxDescArray[NUM_RX_DESC - 1]); =20 return 0; } @@ -4438,6 +4498,40 @@ static void rtl8169_free_tx_desc(struct rtl8169_priv= ate *tp) } } =20 +static int rtl8169_alloc_rx_desc(struct rtl8169_private *tp) +{ + struct rtl8169_rx_ring *ring; + struct pci_dev *pdev =3D tp->pci_dev; + + for (int i =3D 0; i < tp->num_rx_rings; i++) { + ring =3D &tp->rx_ring[i]; + ring->RxDescAllocSize =3D (ring->num_rx_desc + 1) * sizeof(struct RxDesc= ); + ring->RxDescArray =3D dma_alloc_coherent(&pdev->dev, + ring->RxDescAllocSize, + &ring->RxPhyAddr, + GFP_KERNEL); + if (!ring->RxDescArray) + return -1; + } + return 0; +} + +static void rtl8169_free_rx_desc(struct rtl8169_private *tp) +{ + struct rtl8169_rx_ring *ring; + struct pci_dev *pdev =3D tp->pci_dev; + + for (int i =3D 0; i < tp->num_rx_rings; i++) { + ring =3D &tp->rx_ring[i]; + if (ring->RxDescArray) { + dma_free_coherent(&pdev->dev, + ring->RxDescAllocSize, + ring->RxDescArray, + ring->RxPhyAddr); + ring->RxDescArray =3D NULL; + } + } +} =20 static int rtl8169_init_ring(struct rtl8169_private *tp) { @@ -4445,6 +4539,7 @@ static int rtl8169_init_ring(struct rtl8169_private *= tp) =20 rtl8169_init_ring_indexes(tp); rtl8169_tx_desc_init(tp); + rtl8169_rx_desc_init(tp); =20 for (int i =3D 0; i < tp->num_tx_rings; i++) { struct rtl8169_tx_ring *ring =3D &tp->tx_ring[i]; @@ -4452,9 +4547,14 @@ static int rtl8169_init_ring(struct rtl8169_private = *tp) memset(ring->tx_skb, 0x0, sizeof(ring->tx_skb)); } =20 + for (int i =3D 0; i < tp->num_rx_rings; i++) { + struct rtl8169_rx_ring *ring =3D &tp->rx_ring[i]; =20 + memset(ring->Rx_databuff, 0, sizeof(ring->Rx_databuff)); + retval =3D rtl8169_rx_fill(tp, ring); + } =20 - return rtl8169_rx_fill(tp); + return retval; } =20 static void rtl8169_unmap_tx_skb(struct rtl8169_private *tp, @@ -4549,16 +4649,23 @@ static void rtl8169_cleanup(struct rtl8169_private = *tp) rtl8169_init_ring_indexes(tp); } =20 -static void rtl_reset_work(struct rtl8169_private *tp) +static void rtl8169_rx_desc_reset(struct rtl8169_private *tp) { - int i; + for (int i =3D 0; i < tp->num_rx_rings; i++) { + struct rtl8169_rx_ring *ring =3D &tp->rx_ring[i]; + + for (int j =3D 0; j < ring->num_rx_desc; j++) + rtl8169_mark_to_asic(tp, ring->RxDescArray + j); + } +} =20 +static void rtl_reset_work(struct rtl8169_private *tp) +{ netif_stop_queue(tp->dev); =20 rtl8169_cleanup(tp); =20 - for (i =3D 0; i < NUM_RX_DESC; i++) - rtl8169_mark_to_asic(tp->RxDescArray + i); + rtl8169_rx_desc_reset(tp); =20 rtl8169_napi_enable(tp); =20 @@ -5033,9 +5140,11 @@ static inline int rtl8169_fragmented_frame(u32 statu= s) return (status & (FirstFrag | LastFrag)) !=3D (FirstFrag | LastFrag); } =20 -static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) +static inline void rtl8169_rx_csum_default(struct rtl8169_private *tp, + struct sk_buff *skb, + struct RxDesc *desc) { - u32 status =3D opts1 & (RxProtoMask | RxCSFailMask); + u32 status =3D le32_to_cpu(desc->opts1) & (RxProtoMask | RxCSFailMask); =20 if (status =3D=3D RxProtoTCP || status =3D=3D RxProtoUDP) skb->ip_summed =3D CHECKSUM_UNNECESSARY; @@ -5043,22 +5152,67 @@ static inline void rtl8169_rx_csum(struct sk_buff *= skb, u32 opts1) skb_checksum_none_assert(skb); } =20 -static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, int = budget) +static inline void rtl8169_rx_csum(struct rtl8169_private *tp, + struct sk_buff *skb, + struct RxDesc *desc) +{ + rtl8169_rx_csum_default(tp, skb, desc); +} + +static u32 rtl8169_rx_desc_opts1(struct rtl8169_private *tp, struct RxDesc= *desc) +{ + return READ_ONCE(desc->opts1); +} + +static int rtl8169_check_rx_desc_error(struct net_device *dev, + struct rtl8169_private *tp, + u32 status) +{ + int ret =3D 0; + + if (unlikely(status & RxRES)) { + if (status & (RxRWT | RxRUNT)) + dev->stats.rx_length_errors++; + if (status & RxCRC) + dev->stats.rx_crc_errors++; + ret =3D -1; + } + return ret; +} + +static inline void rtl8169_set_desc_dma_addr(struct rtl8169_private *tp, + struct RxDesc *desc, + dma_addr_t mapping) +{ + desc->addr =3D cpu_to_le64(mapping); +} + +static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, + struct rtl8169_rx_ring *ring, int budget) { struct device *d =3D tp_to_dev(tp); int count; =20 - for (count =3D 0; count < budget; count++, tp->cur_rx++) { - unsigned int pkt_size, entry =3D tp->cur_rx % NUM_RX_DESC; - struct RxDesc *desc =3D tp->RxDescArray + entry; + for (count =3D 0; count < budget; count++, ring->cur_rx++) { + unsigned int pkt_size, entry =3D ring->cur_rx % ring->num_rx_desc; + struct RxDesc *desc =3D ring->RxDescArray + entry; struct sk_buff *skb; const void *rx_buf; dma_addr_t addr; u32 status; =20 - status =3D le32_to_cpu(READ_ONCE(desc->opts1)); - if (status & DescOwn) - break; + status =3D le32_to_cpu(rtl8169_rx_desc_opts1(tp, desc)); + + if (status & DescOwn) { + if (!tp->recheck_desc_ownbit) + break; + + tp->recheck_desc_ownbit =3D false; + rtl8169_desc_quirk(tp); + status =3D le32_to_cpu(rtl8169_rx_desc_opts1(tp, desc)); + if (status & DescOwn) + break; + } =20 /* This barrier is needed to keep us from reading * any other fields out of the Rx descriptor until @@ -5066,20 +5220,15 @@ static int rtl_rx(struct net_device *dev, struct rt= l8169_private *tp, int budget */ dma_rmb(); =20 - if (unlikely(status & RxRES)) { + if (rtl8169_check_rx_desc_error(dev, tp, status) < 0) { if (net_ratelimit()) netdev_warn(dev, "Rx ERROR. status =3D %08x\n", status); + dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; =20 if (!(dev->features & NETIF_F_RXALL)) goto release_descriptor; - else if (status & RxRWT || !(status & (RxRUNT | RxCRC))) - goto release_descriptor; } =20 pkt_size =3D status & GENMASK(13, 0); @@ -5095,14 +5244,14 @@ static int rtl_rx(struct net_device *dev, struct rt= l8169_private *tp, int budget goto release_descriptor; } =20 - skb =3D napi_alloc_skb(&tp->r8169napi[0].napi, pkt_size); + skb =3D napi_alloc_skb(&tp->r8169napi[ring->index].napi, pkt_size); if (unlikely(!skb)) { dev->stats.rx_dropped++; goto release_descriptor; } =20 - addr =3D le64_to_cpu(desc->addr); - rx_buf =3D page_address(tp->Rx_databuff[entry]); + addr =3D ring->RxDescPhyAddr[entry]; + rx_buf =3D page_address(ring->Rx_databuff[entry]); =20 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); prefetch(rx_buf); @@ -5111,7 +5260,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8= 169_private *tp, int budget skb->len =3D pkt_size; dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); =20 - rtl8169_rx_csum(skb, status); + rtl8169_rx_csum(tp, skb, desc); skb->protocol =3D eth_type_trans(skb, dev); =20 rtl8169_rx_vlan_tag(desc, skb); @@ -5119,11 +5268,13 @@ static int rtl_rx(struct net_device *dev, struct rt= l8169_private *tp, int budget if (skb->pkt_type =3D=3D PACKET_MULTICAST) dev->stats.multicast++; =20 - napi_gro_receive(&tp->r8169napi[0].napi, skb); + napi_gro_receive(&tp->r8169napi[ring->index].napi, skb); =20 dev_sw_netstats_rx_add(dev, pkt_size); release_descriptor: - rtl8169_mark_to_asic(desc); + rtl8169_set_desc_dma_addr(tp, desc, ring->RxDescPhyAddr[entry]); + dma_wmb(); + rtl8169_mark_to_asic(tp, desc); } =20 return count; @@ -5239,7 +5390,8 @@ static int rtl8169_poll(struct napi_struct *napi, int= budget) for (int i =3D 0; i < tp->num_tx_rings; i++) rtl_tx(dev, tp, &tp->tx_ring[i], budget); =20 - work_done =3D rtl_rx(dev, tp, budget); + for (int i =3D 0; i < tp->num_rx_rings; i++) + work_done +=3D rtl_rx(dev, tp, &tp->rx_ring[i], budget); =20 if (work_done < budget && napi_complete_done(napi, work_done)) rtl_irq_enable(tp); @@ -5371,16 +5523,16 @@ static int rtl8169_close(struct net_device *dev) netif_stop_queue(dev); =20 rtl8169_down(tp); - rtl8169_rx_clear(tp); =20 + for (int i =3D 0; i < tp->num_rx_rings; i++) + rtl8169_rx_clear(tp, &tp->rx_ring[i]); =20 rtl8169_free_irq(tp); =20 phy_disconnect(tp->phydev); =20 - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray =3D NULL; + rtl8169_free_rx_desc(tp); + rtl8169_free_tx_desc(tp); =20 pm_runtime_put_sync(&pdev->dev); @@ -5411,11 +5563,12 @@ static int rtl_open(struct net_device *dev) * dma_alloc_coherent provides more. */ =20 - tp->RxDescArray =3D dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); if (rtl8169_alloc_tx_desc(tp) < 0) goto err_free_tx_0; =20 + if (rtl8169_alloc_rx_desc(tp) < 0) + goto err_free_rx_1; + retval =3D rtl8169_init_ring(tp); if (retval < 0) goto err_free_rx_1; @@ -5444,11 +5597,10 @@ static int rtl_open(struct net_device *dev) rtl8169_free_irq(tp); err_release_fw_2: rtl_release_firmware(tp); - rtl8169_rx_clear(tp); + for (int i =3D 0; i < tp->num_rx_rings; i++) + rtl8169_rx_clear(tp, &tp->rx_ring[i]); err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray =3D NULL; + rtl8169_free_rx_desc(tp); err_free_tx_0: rtl8169_free_tx_desc(tp); goto out; --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 CFCB9377561; Mon, 20 Apr 2026 02:20:55 +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=1776651657; cv=none; b=tYtEDdQ2covPQdbTkdJ3GoIp+V3dcn14CvoyIE4zCmgvgp6ubx/HqsI/HIalkR30gWU49FkYbRtJlLqOsNbNOFQsiS6F3TmbWNrqE0auMcna+fSJfTVYOh+ZL2E9K/8MltE4gMmt4RYRNow/+DRA8nMG1OlkoOcHOt0a4sBo+LQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651657; c=relaxed/simple; bh=gTHAs4pKbt9xyqXnbYDq1GdK9P5lg9hXqOwZ3atefF4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=b1ZI4nEe1r+9CGU69zY2hu0dg2zIwTNTNWFzjotU6HiVWqZUdd0l7hEDB2mCO46NNKZDqPy8jM1J19RJCKYusBCmGJtd2m6c389t97tyyr9cGcq1ZNRA3bmRFG+xifnR7CFPM7Qdk3K/3fK4yikOumXTShxtYK2RacO5nY0lGok= 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=T4gle/az; 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="T4gle/az" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KEBn8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651615; bh=bPzwPBKweEJb9wQqUsnydxqVHpbxWLM+b+Xf3VU5hRo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=T4gle/azB0OXq1ChJJgeqhQkpF1nvLJzpXSsr7ZlHxsMlPOV8O0LulgPTrUjaomB8 oTDxTRhshUCBxRJy0eBe/C/U0GGpI/yejiiZNGoR0LJMWO/IAHH/7rmgHP41YBlOQ2 8ZaToBUxxsxo7RymjZO4nRMzAISljhvQmXpJaWhG8270Ne54GnWKC/zrKvfIoVXHd8 tjb8XjMFfuxUW+YV7OL03TO495TYJWvMSUDnVBgUC/tVdVgTQEBpGVmfhy7fT9Sjk9 5K+2GU0uhvzR6V+5us2ej/4CoT00LKQZHxZ17fN54rYMHqumH/JnvsDHoptjrZEOTa hgnxP1ZBVrt4Q== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KEBn8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:14 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:14 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:14 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 5/9] r8169: add support for msix Date: Mon, 20 Apr 2026 10:19:53 +0800 Message-ID: <20260420021957.1756-6-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch add support for msix. But we still use MSI here. And we force nvecs to 1. We will modify it in rss patch. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 162 ++++++++++++++++++++-- 1 file changed, 151 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 52e690eba644..7d493342ab4b 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1764,26 +1764,40 @@ static u32 rtl_get_events(struct rtl8169_private *t= p) =20 static void rtl_ack_events(struct rtl8169_private *tp, u32 bits) { - if (rtl_is_8125(tp)) + if (rtl_is_8125(tp)) { RTL_W32(tp, IntrStatus_8125, bits); - else + if (tp->features & RTL_FEATURE_MSIX) { + RTL_W32(tp, ISR_V2_8125, 0xffffffff); + RTL_W32(tp, ISR_V4_L2_8125, 0xffffffff); + } + } else { RTL_W16(tp, IntrStatus, bits); + } } =20 static void rtl_irq_disable(struct rtl8169_private *tp) { - if (rtl_is_8125(tp)) + if (rtl_is_8125(tp)) { RTL_W32(tp, IntrMask_8125, 0); - else + if (tp->features & RTL_FEATURE_MSIX) { + RTL_W32(tp, IMR_V2_CLEAR_REG_8125, 0xffffffff); + RTL_W32(tp, IMR_V4_L2_CLEAR_REG_8125, 0xffffffff); + } + } else { RTL_W16(tp, IntrMask, 0); + } } =20 static void rtl_irq_enable(struct rtl8169_private *tp) { - if (rtl_is_8125(tp)) - RTL_W32(tp, IntrMask_8125, tp->irq_mask); - else + if (rtl_is_8125(tp)) { + if (tp->features & RTL_FEATURE_MSIX) + RTL_W32(tp, IMR_V2_SET_REG_8125, tp->irq_mask); + else + RTL_W32(tp, IntrMask_8125, tp->irq_mask); + } else { RTL_W16(tp, IntrMask, tp->irq_mask); + } } =20 static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) @@ -2894,6 +2908,10 @@ static void rtl_software_parameter_initialize(struct= rtl8169_private *tp) tp->InitRxDescType =3D RX_DESC_RING_TYPE_DEAFULT; tp->HwCurrIsrVer =3D tp->HwSuppIsrVer; =20 + /* This just force nvecs, and will be remove in the following patch*/ + tp->min_irq_nvecs =3D 1; + tp->max_irq_nvecs =3D 1; + rtl_setup_mqs_reg(tp); rtl_set_ring_size(tp, NUM_RX_DESC, NUM_TX_DESC); } @@ -5321,6 +5339,44 @@ static void rtl8169_free_irq(struct rtl8169_private = *tp) } } =20 +static void rtl8169_disable_hw_interrupt_msix(struct rtl8169_private *tp, = int message_id) +{ + RTL_W32(tp, IMR_V2_CLEAR_REG_8125, BIT(message_id)); +} + +static void rtl8169_clear_hw_isr(struct rtl8169_private *tp, int message_i= d) +{ + RTL_W32(tp, ISR_V2_8125, BIT(message_id)); +} + +static void rtl8169_enable_hw_interrupt_msix(struct rtl8169_private *tp, i= nt message_id) +{ + RTL_W32(tp, IMR_V2_SET_REG_8125, BIT(message_id)); +} + +static irqreturn_t rtl8169_interrupt_msix(int irq, void *dev_instance) +{ + struct rtl8169_napi *napi =3D dev_instance; + struct rtl8169_private *tp =3D napi->priv; + int message_id =3D napi->index; + + rtl8169_disable_hw_interrupt_msix(tp, message_id); + + rtl8169_clear_hw_isr(tp, message_id); + + if (message_id =3D=3D MSIX_ID_V4_LINKCHG) { + phy_mac_interrupt(tp->phydev); + rtl8169_enable_hw_interrupt_msix(tp, message_id); + return IRQ_HANDLED; + } + + tp->recheck_desc_ownbit =3D true; + + napi_schedule(&napi->napi); + + return IRQ_HANDLED; +} + static int rtl8169_request_irq(struct rtl8169_private *tp) { struct net_device *dev =3D tp->dev; @@ -5331,10 +5387,14 @@ static int rtl8169_request_irq(struct rtl8169_priva= te *tp) =20 for (int i =3D 0; i < tp->irq_nvecs; i++) { irq =3D &tp->irq_tbl[i]; + if (tp->features & RTL_FEATURE_MSIX && tp->HwCurrIsrVer > 1) + irq->handler =3D rtl8169_interrupt_msix; + else + irq->handler =3D rtl8169_interrupt; =20 napi =3D &tp->r8169napi[i]; snprintf(irq->name, len, "%s-%d", dev->name, i); - rc =3D pci_request_irq(tp->pci_dev, i, rtl8169_interrupt, NULL, napi, ir= q->name); + rc =3D pci_request_irq(tp->pci_dev, i, irq->handler, NULL, napi, irq->na= me); =20 if (rc) break; @@ -5786,10 +5846,18 @@ static const struct net_device_ops rtl_netdev_ops = =3D { =20 static void rtl_set_irq_mask(struct rtl8169_private *tp) { - tp->irq_mask =3D RxOK | RxErr | TxOK | TxErr | LinkChg; + if (tp->features & RTL_FEATURE_MSIX) { + tp->irq_mask =3D ISRIMR_V6_LINKCHG; + for (int i =3D 0; i < tp->num_tx_rings; i++) + tp->irq_mask |=3D ISRIMR_V6_TOK_Q0 << i; + for (int i =3D 0; i < tp->num_rx_rings; i++) + tp->irq_mask |=3D ISRIMR_V6_ROK_Q0 << i; + } else { + tp->irq_mask =3D RxOK | RxErr | TxOK | TxErr | LinkChg; =20 - if (tp->mac_version <=3D RTL_GIGA_MAC_VER_06) - tp->irq_mask |=3D SYSErr | RxFIFOOver; + if (tp->mac_version <=3D RTL_GIGA_MAC_VER_06) + tp->irq_mask |=3D SYSErr | RxFIFOOver; + } } =20 static int rtl_alloc_irq(struct rtl8169_private *tp) @@ -5817,6 +5885,18 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) if (nvecs < 0) nvecs =3D pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); =20 + tp->features &=3D ~(RTL_FEATURE_MSIX | RTL_FEATURE_MSI); + + if (nvecs > 0) { + tp->irq_nvecs =3D nvecs; + tp->irq =3D pci_irq_vector(pdev, 0); + if (nvecs > 1) + tp->features |=3D RTL_FEATURE_MSIX; + else if (pci_dev_msi_enabled(pdev)) + tp->features |=3D RTL_FEATURE_MSI; + return 0; + } + tp->irq =3D pdev->irq; tp->irq_nvecs =3D 1; =20 @@ -6087,6 +6167,52 @@ static bool rtl_aspm_is_safe(struct rtl8169_private = *tp) return false; } =20 +static int rtl8169_poll_msix_rx(struct napi_struct *napi, int budget) +{ + struct rtl8169_napi *r8169_napi =3D container_of(napi, struct rtl8169_nap= i, napi); + struct rtl8169_private *tp =3D r8169_napi->priv; + struct net_device *dev =3D tp->dev; + const int message_id =3D r8169_napi->index; + int work_done =3D 0; + + if (message_id < tp->num_rx_rings) + work_done +=3D rtl_rx(dev, tp, &tp->rx_ring[message_id], budget); + + if (work_done < budget && napi_complete_done(napi, work_done)) + rtl8169_enable_hw_interrupt_msix(tp, message_id); + + return work_done; +} + +static int rtl8169_poll_msix_tx(struct napi_struct *napi, int budget) +{ + struct rtl8169_napi *r8169_napi =3D container_of(napi, struct rtl8169_nap= i, napi); + struct rtl8169_private *tp =3D r8169_napi->priv; + struct net_device *dev =3D tp->dev; + unsigned int work_done =3D 0; + const int message_id =3D r8169_napi->index; + int tx_ring_idx =3D message_id - 8; + + if (tx_ring_idx >=3D 0 && tx_ring_idx < tp->num_tx_rings) + work_done +=3D rtl_tx(dev, tp, &tp->tx_ring[tx_ring_idx], budget); + + if (work_done < budget && napi_complete_done(napi, work_done)) + rtl8169_enable_hw_interrupt_msix(tp, message_id); + + return work_done; +} + +static int rtl8169_poll_msix_other(struct napi_struct *napi, int budget) +{ + struct rtl8169_napi *r8169_napi =3D container_of(napi, struct rtl8169_nap= i, napi); + struct rtl8169_private *tp =3D r8169_napi->priv; + const int message_id =3D r8169_napi->index; + + napi_complete_done(napi, budget); + rtl8169_enable_hw_interrupt_msix(tp, message_id); + + return 1; +} =20 static void r8169_init_napi(struct rtl8169_private *tp) { @@ -6095,6 +6221,20 @@ static void r8169_init_napi(struct rtl8169_private *= tp) int (*poll)(struct napi_struct *napi, int budget); =20 poll =3D rtl8169_poll; + if (tp->features & RTL_FEATURE_MSIX) { + switch (tp->HwCurrIsrVer) { + case 6: + if (i < R8127_MAX_RX_QUEUES) + poll =3D rtl8169_poll_msix_rx; + else if (i > 7 && i < 16) + poll =3D rtl8169_poll_msix_tx; + else + poll =3D rtl8169_poll_msix_other; + break; + default: + break; + } + } netif_napi_add(tp->dev, &r8169napi->napi, poll); r8169napi->priv =3D tp; r8169napi->index =3D i; --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 37FBE377579; Mon, 20 Apr 2026 02:20:56 +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=1776651657; cv=none; b=PxPtIi8Kl+BXAMMGD1YPJiNbZgE4oMDTKXbamyYbeSF/fINPgcMA9RKe90njhmOx4+GIqjExSMiUFyGhF3kLeaBG01fIKDatn4JPNJAp4YA2EvhHz61UztVznPYg51VgMDEwU4NARbL7+5KuS7E9yuWFXwpAwl+wAQCgXXjZrqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651657; c=relaxed/simple; bh=0MQ114wC8eOAw7NUpEjTS13PtJ63qar0k1jaxXAjyWw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HuIm2r/HpVX/1/RDL923SrasxvZWcxBozG3mzDmftH46NqMZjfiGfDIy6qeJGSTzopZ4n/2fYVb/QeOoqu5z7Bq1svL4EduaJVqsdLqkWhRp0E1bwkTngGBNupZCD78ZA1HphvcKMqzKw83fP2rjuHs6+FvlgOF9GurwbyFfn/A= 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=vySU4PXW; 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="vySU4PXW" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KFBl8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651615; bh=Gsk7mzSm2HhUX3oQrymdkV6N6yErhy7ZgenuOBqhUHY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=vySU4PXWRTl87DtdDt9+6g0d9ufYAtZiT3ZnBxCISB3Py5LFGFU4yQM9hCIzSBePO 611kecv0O2gjqwSw1xRRXUeI9MI9ytTvwl37GwLtCa/1pkRGvd46FTu06nRQ8IJ5CB /XcqX3QZ/2dpVgG6v+RXtslod2IF/dFbdcQms/oea2+eED/RmOBs/NzecKRRY/yuF8 6NSQXyTpUB77lphJXe16baOmI2sDPYczqjiRuJuFG39uBw9a4LMz6N3PKgfKfk5ZP2 pdM6FQurPuXeTeuMAEHgilxy1lhc+zCoiLNoPM5Ytyk9FSVrLCLis9HzZS9NFce8tj XOc9yhcEyINww== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KFBl8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:15 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:14 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:14 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 6/9] r8169: enable msix for RTL8127 Date: Mon, 20 Apr 2026 10:19:54 +0800 Message-ID: <20260420021957.1756-7-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch enables msix for RTL8127. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 7d493342ab4b..622ee8905a05 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4102,6 +4102,16 @@ DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond) return r8168_mac_ocp_read(tp, 0xe00e) & BIT(13); } =20 + +static void rtl8125_hw_set_interrupt_type(struct rtl8169_private *tp) +{ + u8 tmp; + + tmp =3D RTL_R8(tp, INT_CFG0_8125); + tmp |=3D INT_CFG0_ENABLE_8125; + RTL_W8(tp, INT_CFG0_8125, tmp); +} + static void rtl_hw_start_8125_common(struct rtl8169_private *tp) { rtl_pcie_state_l2l3_disable(tp); @@ -4110,6 +4120,9 @@ static void rtl_hw_start_8125_common(struct rtl8169_p= rivate *tp) RTL_W32(tp, RSS_CTRL_8125, 0); RTL_W16(tp, Q_NUM_CTRL_8125, 0); =20 + if (tp->features & RTL_FEATURE_MSIX) + rtl8125_hw_set_interrupt_type(tp); + /* disable UPS */ r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000); =20 --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 0BC05377574; Mon, 20 Apr 2026 02:20:55 +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=1776651659; cv=none; b=slzlm7TZ+YglIN+/pZ5NlVWxoaSAUmJrdHCSESKYrhrDGJTo5t+gAP61HjpIfgDzCk4PoSIU9TBkaCIDQrxzI4VMSt8P0+GY6UqPyNWnfwoq5bYspQ2pmYtJB5Mu7c6cJbQN+N4hzxx7NqQYHq4l/hrn1RE0Mk2GebER7jn7/+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651659; c=relaxed/simple; bh=9uTKNSP7e2S1OSDwRNMMw7aisjqpienkyGsNONMrOIg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NgE3Zr7LXH+opV9pCgR/ySwaEi4/gdk/xE2lN/Jpu85XYEqS3QIKYePqCn5avXOvHCWWDvoR7/D8+6x6ixcdqC8nugvuUSp6XSc1HBnLaBL0Knz19mG34kabEsUZyEMAozPFU7Zjd+eJKxtXzsqv6MJtcJmqZQEmKHpijGhvxHw= 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=D26y+2gg; 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="D26y+2gg" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KFBm8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651615; bh=oiLdHzuUFpkCR2n4q9jI1qPtuuW7sT+noFPY++D9neM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=D26y+2gg4BdlI77D5yEu1bv2exystq95MyttVxBxLb5Wa7V2figqxw6pEIBpeb4RK W08Yl59ABpdCjWWjYS03tOjR2Fig7OjV29KDcxS6gopEddPNOVQ5J1hvPmBE2pMzoS xWUb7PUb0+WDBuMIBpdv1Dm9kKFK2YIcUGYy5svLM5v3z0RSRiHtiLjZEqo4IZbNiy N4+6ecviIRhEvp/A7wcQnYO9fxEAia1x4c5Zhuta+zM3uEMDFtNYwDa5c2lgQymEOS nxNBnd5MufNzCVFyNzk2JzIovsOTUSWojpqeoxgQ2411riJcu8kBoQlXqpxCCZlKLQ lPCHOMl/vlooA== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KFBm8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:15 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:14 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:14 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 7/9] r8169: add support and enable rss Date: Mon, 20 Apr 2026 10:19:55 +0800 Message-ID: <20260420021957.1756-8-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch adds support and enable rss for RTL8127. We remove the setting nvecs 1 to support multi queue and rss. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 340 ++++++++++++++++++++-- 1 file changed, 321 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 622ee8905a05..b3f15e6fd5e9 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -718,6 +718,21 @@ struct RxDesc { __le64 addr; }; =20 +struct RxDescRss { + union { + __le64 addr; + struct { + __le32 RSSInfo; + __le32 RSSResult; + } RxDescRSSDWord; + }; + + struct { + __le32 opts2; + __le32 opts1; + } RxDescOpts; +}; + enum features { RTL_FEATURE_MSI =3D (1 << 1), RTL_FEATURE_MSIX =3D (1 << 2), @@ -853,9 +868,13 @@ struct rtl8169_private { u16 imr_reg[R8169_MAX_MSIX_VEC]; unsigned int num_tx_rings; unsigned int num_rx_rings; + u32 rss_flags; u16 cp_cmd; u16 tx_lpi_timer; u32 irq_mask; + u8 rss_key[RTL8127_RSS_KEY_SIZE]; + u8 rss_indir_tbl[RTL8127_MAX_INDIRECTION_TABLE_ENTRIES]; + u8 HwSuppIndirTblEntries; u16 HwSuppNumTxQueues; u16 HwSuppNumRxQueues; u8 min_irq_nvecs; @@ -1698,6 +1717,13 @@ static bool rtl_dash_is_enabled(struct rtl8169_priva= te *tp) } } =20 +static bool rtl_check_rss_support(struct rtl8169_private *tp) +{ + if (tp->mac_version =3D=3D RTL_GIGA_MAC_VER_80) + return true; + return false; +} + static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp) { switch (tp->mac_version) { @@ -2001,9 +2027,20 @@ static inline u32 rtl8169_tx_vlan_tag(struct sk_buff= *skb) TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; } =20 -static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) +static void rtl8169_rx_vlan_tag(struct rtl8169_private *tp, + struct RxDesc *desc, + struct sk_buff *skb) { - u32 opts2 =3D le32_to_cpu(desc->opts2); + u32 opts2; + + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + opts2 =3D le32_to_cpu(((struct RxDescRss *)desc)->RxDescOpts.opts2); + break; + default: + opts2 =3D le32_to_cpu(desc->opts2); + break; + } =20 if (opts2 & RxVlanTag) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); @@ -2884,6 +2921,14 @@ static void rtl_setup_mqs_reg(struct rtl8169_private= *tp) tp->imr_reg[i] =3D (u16)(IntrMask1_8125 + (i - 1) * 4); } =20 +static void rtl8169_init_rss(struct rtl8169_private *tp) +{ + for (int i =3D 0; i < tp->HwSuppIndirTblEntries; i++) + tp->rss_indir_tbl[i] =3D ethtool_rxfh_indir_default(i, tp->num_rx_rings); + + netdev_rss_key_fill(tp->rss_key, RTL8127_RSS_KEY_SIZE); +} + static void rtl_software_parameter_initialize(struct rtl8169_private *tp) { tp->num_rx_rings =3D 1; @@ -2895,6 +2940,7 @@ static void rtl_software_parameter_initialize(struct = rtl8169_private *tp) tp->max_irq_nvecs =3D R8127_MAX_IRQ; tp->HwSuppNumTxQueues =3D R8127_MAX_TX_QUEUES; tp->HwSuppNumRxQueues =3D R8127_MAX_RX_QUEUES; + tp->HwSuppIndirTblEntries =3D RTL8127_MAX_INDIRECTION_TABLE_ENTRIES; tp->HwSuppIsrVer =3D 6; break; default: @@ -2908,10 +2954,6 @@ static void rtl_software_parameter_initialize(struct= rtl8169_private *tp) tp->InitRxDescType =3D RX_DESC_RING_TYPE_DEAFULT; tp->HwCurrIsrVer =3D tp->HwSuppIsrVer; =20 - /* This just force nvecs, and will be remove in the following patch*/ - tp->min_irq_nvecs =3D 1; - tp->max_irq_nvecs =3D 1; - rtl_setup_mqs_reg(tp); rtl_set_ring_size(tp, NUM_RX_DESC, NUM_TX_DESC); } @@ -3038,6 +3080,76 @@ static void rtl_set_rx_max_size(struct rtl8169_priva= te *tp) RTL_W16(tp, RxMaxSize, R8169_RX_BUF_SIZE + 1); } =20 +static void rtl8169_store_rss_key(struct rtl8169_private *tp) +{ + const u16 rss_key_reg =3D RSS_KEY_8125; + u32 i, rss_key_size =3D sizeof(tp->rss_key); + u32 *rss_key =3D (u32 *)tp->rss_key; + + /* Write redirection table to HW */ + for (i =3D 0; i < rss_key_size; i +=3D 4) + RTL_W32(tp, rss_key_reg + i, *rss_key++); +} + +static void rtl8169_store_reta(struct rtl8169_private *tp) +{ + u16 indir_tbl_reg =3D RSS_INDIRECTION_TBL_8125_V2; + u32 i, reta_entries =3D tp->HwSuppIndirTblEntries; + u32 reta =3D 0; + u8 *indir_tbl =3D tp->rss_indir_tbl; + + /* Write redirection table to HW */ + for (i =3D 0; i < reta_entries; i++) { + reta |=3D indir_tbl[i] << (i & 0x3) * 8; + if ((i & 3) =3D=3D 3) { + RTL_W32(tp, indir_tbl_reg, reta); + indir_tbl_reg +=3D 4; + reta =3D 0; + } + } +} + +static int rtl8169_set_rss_hash_opt(struct rtl8169_private *tp) +{ + u32 rss_flags =3D tp->rss_flags; + u32 hash_mask_len; + u32 rss_ctrl; + + rss_ctrl =3D ilog2(tp->num_rx_rings); + rss_ctrl &=3D (BIT(0) | BIT(1) | BIT(2)); + rss_ctrl <<=3D RSS_CPU_NUM_OFFSET; + + /* Perform hash on these packet types */ + rss_ctrl |=3D RSS_CTRL_TCP_IPV4_SUPP + | RSS_CTRL_IPV4_SUPP + | RSS_CTRL_IPV6_SUPP + | RSS_CTRL_IPV6_EXT_SUPP + | RSS_CTRL_TCP_IPV6_SUPP + | RSS_CTRL_TCP_IPV6_EXT_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) + rss_ctrl |=3D RSS_CTRL_UDP_IPV4_SUPP; + + if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) + rss_ctrl |=3D RSS_CTRL_UDP_IPV6_SUPP | + RSS_CTRL_UDP_IPV6_EXT_SUPP; + + hash_mask_len =3D ilog2(tp->HwSuppIndirTblEntries); + hash_mask_len &=3D (BIT(0) | BIT(1) | BIT(2)); + rss_ctrl |=3D hash_mask_len << RSS_MASK_BITS_OFFSET; + + RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); + + return 0; +} + +static void rtl_set_rss_config(struct rtl8169_private *tp) +{ + rtl8169_set_rss_hash_opt(tp); + rtl8169_store_reta(tp); + rtl8169_store_rss_key(tp); +} + static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp) { /* @@ -4102,6 +4214,29 @@ DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond) return r8168_mac_ocp_read(tp, 0xe00e) & BIT(13); } =20 +static void rtl8125_set_tx_q_num(struct rtl8169_private *tp) +{ + u16 mac_ocp_data; + + mac_ocp_data =3D r8168_mac_ocp_read(tp, 0xe63e); + mac_ocp_data &=3D ~(BIT(11) | BIT(10)); + mac_ocp_data |=3D ((ilog2(tp->num_tx_rings) & 0x03) << 10); + r8168_mac_ocp_write(tp, 0xe63e, mac_ocp_data); +} + +static void rtl8125_set_rx_q_num(struct rtl8169_private *tp) +{ + u16 q_ctrl; + u16 rx_q_num; + + rx_q_num =3D (u16)ilog2(tp->num_rx_rings); + rx_q_num &=3D (BIT(0) | BIT(1) | BIT(2)); + rx_q_num <<=3D 2; + q_ctrl =3D RTL_R16(tp, Q_NUM_CTRL_8125); + q_ctrl &=3D ~(BIT(2) | BIT(3) | BIT(4)); + q_ctrl |=3D rx_q_num; + RTL_W16(tp, Q_NUM_CTRL_8125, q_ctrl); +} =20 static void rtl8125_hw_set_interrupt_type(struct rtl8169_private *tp) { @@ -4142,6 +4277,13 @@ static void rtl_hw_start_8125_common(struct rtl8169_= private *tp) tp->mac_version =3D=3D RTL_GIGA_MAC_VER_80) RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02); =20 + /* enable rx descriptor type v4 and set queue num for rss*/ + if (tp->rss_enable) { + rtl8125_set_rx_q_num(tp); + rtl8125_set_tx_q_num(tp); + RTL_W8(tp, 0xd8, RTL_R8(tp, 0xd8) | 0x02); + } + if (tp->mac_version =3D=3D RTL_GIGA_MAC_VER_80) r8168_mac_ocp_modify(tp, 0xe614, 0x0f00, 0x0f00); else if (tp->mac_version =3D=3D RTL_GIGA_MAC_VER_70) @@ -4378,6 +4520,12 @@ static void rtl_hw_start(struct rtl8169_private *tp) rtl_hw_aspm_clkreq_enable(tp, true); rtl_set_rx_max_size(tp); rtl_set_rx_tx_desc_registers(tp); + if (rtl_is_8125(tp)) { + if (tp->rss_enable) + rtl_set_rss_config(tp); + else + RTL_W32(tp, RSS_CTRL_8125, 0x00); + } rtl_lock_config_regs(tp); =20 rtl_jumbo_config(tp); @@ -4405,6 +4553,16 @@ static int rtl8169_change_mtu(struct net_device *dev= , int new_mtu) return 0; } =20 +static void rtl8169_mark_to_asic_rss(struct RxDescRss *descrss) +{ + u32 eor =3D le32_to_cpu(descrss->RxDescOpts.opts1) & RingEnd; + + descrss->RxDescOpts.opts2 =3D 0; + /* Force memory writes to complete before releasing descriptor */ + dma_wmb(); + WRITE_ONCE(descrss->RxDescOpts.opts1, cpu_to_le32(DescOwn | eor | R8169_R= X_BUF_SIZE)); +} + static void rtl8169_mark_to_asic_default(struct RxDesc *desc) { u32 eor =3D le32_to_cpu(desc->opts1) & RingEnd; @@ -4417,7 +4575,14 @@ static void rtl8169_mark_to_asic_default(struct RxDe= sc *desc) =20 static void rtl8169_mark_to_asic(struct rtl8169_private *tp, struct RxDesc= *desc) { - rtl8169_mark_to_asic_default(desc); + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + rtl8169_mark_to_asic_rss((struct RxDescRss *)desc); + break; + default: + rtl8169_mark_to_asic_default(desc); + break; + } } =20 static struct page *rtl8169_alloc_rx_data(struct rtl8169_private *tp, @@ -4441,7 +4606,13 @@ static struct page *rtl8169_alloc_rx_data(struct rtl= 8169_private *tp, } =20 ring->RxDescPhyAddr[index] =3D mapping; - desc->addr =3D cpu_to_le64(mapping); + if (tp->InitRxDescType =3D=3D RX_DESC_RING_TYPE_RSS) { + struct RxDescRss *descrss =3D (struct RxDescRss *)(ring->RxDescArray) + = index; + + descrss->addr =3D cpu_to_le64(mapping); + } else { + desc->addr =3D cpu_to_le64(mapping); + } rtl8169_mark_to_asic(tp, desc); =20 return data; @@ -4468,9 +4639,21 @@ static void rtl8169_mark_as_last_descriptor_default(= struct RxDesc *desc) desc->opts1 |=3D cpu_to_le32(RingEnd); } =20 +static void rtl8169_mark_as_last_descriptor_rss(struct RxDescRss *descrss) +{ + descrss->RxDescOpts.opts1 |=3D cpu_to_le32(RingEnd); +} + static void rtl8169_mark_as_last_descriptor(struct rtl8169_private *tp, st= ruct RxDesc *desc) { - rtl8169_mark_as_last_descriptor_default(desc); + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + rtl8169_mark_as_last_descriptor_rss((struct RxDescRss *)desc); + break; + default: + rtl8169_mark_as_last_descriptor_default(desc); + break; + } } =20 static int rtl8169_rx_fill(struct rtl8169_private *tp, struct rtl8169_rx_r= ing *ring) @@ -5171,6 +5354,28 @@ static inline int rtl8169_fragmented_frame(u32 statu= s) return (status & (FirstFrag | LastFrag)) !=3D (FirstFrag | LastFrag); } =20 +static inline void rtl8169_rx_hash(struct rtl8169_private *tp, + struct RxDescRss *desc, + struct sk_buff *skb) +{ + u32 rss_header_info; + u32 hash_val; + + if (!(tp->dev->features & NETIF_F_RXHASH)) + return; + + rss_header_info =3D le32_to_cpu(desc->RxDescRSSDWord.RSSInfo); + + if (!(rss_header_info & RTL8127_RXS_RSS_L3_TYPE_MASK_V4)) + return; + + hash_val =3D le32_to_cpu(desc->RxDescRSSDWord.RSSResult); + + skb_set_hash(skb, hash_val, + (RTL8127_RXS_RSS_L4_TYPE_MASK_V4 & rss_header_info) ? + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); +} + static inline void rtl8169_rx_csum_default(struct rtl8169_private *tp, struct sk_buff *skb, struct RxDesc *desc) @@ -5183,16 +5388,41 @@ static inline void rtl8169_rx_csum_default(struct r= tl8169_private *tp, skb_checksum_none_assert(skb); } =20 +static inline void rtl8169_rx_csum_rss(struct rtl8169_private *tp, + struct sk_buff *skb, + struct RxDescRss *descrss) +{ + u32 opts1 =3D le32_to_cpu(descrss->RxDescOpts.opts1); + + if (((opts1 & RxTCPT_v4) && !(opts1 & RxTCPF_v4)) || + ((opts1 & RxUDPT_v4) && !(opts1 & RxUDPF_v4))) + skb->ip_summed =3D CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +} + static inline void rtl8169_rx_csum(struct rtl8169_private *tp, struct sk_buff *skb, struct RxDesc *desc) { - rtl8169_rx_csum_default(tp, skb, desc); + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + rtl8169_rx_csum_rss(tp, skb, (struct RxDescRss *)desc); + break; + default: + rtl8169_rx_csum_default(tp, skb, desc); + break; + } } =20 static u32 rtl8169_rx_desc_opts1(struct rtl8169_private *tp, struct RxDesc= *desc) { - return READ_ONCE(desc->opts1); + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + return READ_ONCE(((struct RxDescRss *)desc)->RxDescOpts.opts1); + default: + return READ_ONCE(desc->opts1); + } } =20 static int rtl8169_check_rx_desc_error(struct net_device *dev, @@ -5201,12 +5431,25 @@ static int rtl8169_check_rx_desc_error(struct net_d= evice *dev, { int ret =3D 0; =20 - if (unlikely(status & RxRES)) { - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - ret =3D -1; + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + if (unlikely(status & RxRES_RSS)) { + if (status & RxRUNT_RSS) + dev->stats.rx_length_errors++; + if (status & RxCRC_RSS) + dev->stats.rx_crc_errors++; + ret =3D -1; + } + break; + default: + if (unlikely(status & RxRES)) { + if (status & (RxRWT | RxRUNT)) + dev->stats.rx_length_errors++; + if (status & RxCRC) + dev->stats.rx_crc_errors++; + ret =3D -1; + } + break; } return ret; } @@ -5215,7 +5458,14 @@ static inline void rtl8169_set_desc_dma_addr(struct = rtl8169_private *tp, struct RxDesc *desc, dma_addr_t mapping) { - desc->addr =3D cpu_to_le64(mapping); + switch (tp->InitRxDescType) { + case RX_DESC_RING_TYPE_RSS: + ((struct RxDescRss *)desc)->addr =3D cpu_to_le64(mapping); + break; + default: + desc->addr =3D cpu_to_le64(mapping); + break; + } } =20 static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, @@ -5291,10 +5541,13 @@ static int rtl_rx(struct net_device *dev, struct rt= l8169_private *tp, skb->len =3D pkt_size; dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); =20 + if (tp->rss_enable) + rtl8169_rx_hash(tp, (struct RxDescRss *)desc, skb); + rtl8169_rx_csum(tp, skb, desc); skb->protocol =3D eth_type_trans(skb, dev); =20 - rtl8169_rx_vlan_tag(desc, skb); + rtl8169_rx_vlan_tag(tp, desc, skb); =20 if (skb->pkt_type =3D=3D PACKET_MULTICAST) dev->stats.multicast++; @@ -5873,6 +6126,45 @@ static void rtl_set_irq_mask(struct rtl8169_private = *tp) } } =20 +static void rtl8169_double_check_rss_support(struct rtl8169_private *tp) +{ + if (tp->HwCurrIsrVer > 1) { + if (!(tp->features & RTL_FEATURE_MSIX) || tp->irq_nvecs < tp->min_irq_nv= ecs) + tp->HwCurrIsrVer =3D 1; + } + + if (tp->rss_support && tp->HwCurrIsrVer > 1) { + u8 rss_queue_num =3D netif_get_num_default_rss_queues(); + + tp->num_rx_rings =3D min(rss_queue_num, tp->HwSuppNumRxQueues); + if (!(tp->num_rx_rings >=3D 2 && tp->irq_nvecs >=3D tp->min_irq_nvecs)) + tp->num_rx_rings =3D 1; + } + + if (tp->num_rx_rings >=3D 2) { + tp->rss_enable =3D 1; + tp->InitRxDescType =3D RX_DESC_RING_TYPE_RSS; + } else { + tp->rss_enable =3D 0; + if (tp->irq_nvecs > 1) { + pci_free_irq_vectors(tp->pci_dev); + + tp->irq_nvecs =3D pci_alloc_irq_vectors(tp->pci_dev, 1, 1, PCI_IRQ_ALL_= TYPES); + + if (tp->irq_nvecs > 0) { + tp->irq =3D pci_irq_vector(tp->pci_dev, 0); + } else { + tp->irq =3D tp->pci_dev->irq; + tp->irq_nvecs =3D 1; + } + + tp->features &=3D ~RTL_FEATURE_MSIX; + if (pci_dev_msi_enabled(tp->pci_dev)) + tp->features |=3D RTL_FEATURE_MSI; + } + } +} + static int rtl_alloc_irq(struct rtl8169_private *tp) { struct pci_dev *pdev =3D tp->pci_dev; @@ -6346,6 +6638,7 @@ static int rtl_init_one(struct pci_dev *pdev, const s= truct pci_device_id *ent) =20 tp->dash_type =3D rtl_get_dash_type(tp); tp->dash_enabled =3D rtl_dash_is_enabled(tp); + tp->rss_support =3D rtl_check_rss_support(tp); =20 tp->cp_cmd =3D RTL_R16(tp, CPlusCmd) & CPCMD_MASK; =20 @@ -6367,6 +6660,10 @@ static int rtl_init_one(struct pci_dev *pdev, const = struct pci_device_id *ent) if (rc < 0) return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n"); =20 + rtl8169_double_check_rss_support(tp); + + if (tp->rss_support) + rtl8169_init_rss(tp); =20 INIT_WORK(&tp->wk.work, rtl_task); disable_work(&tp->wk.work); @@ -6388,6 +6685,11 @@ static int rtl_init_one(struct pci_dev *pdev, const = struct pci_device_id *ent) dev->vlan_features =3D NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; dev->priv_flags |=3D IFF_LIVE_ADDR_CHANGE; =20 + if (tp->rss_support) { + dev->hw_features |=3D NETIF_F_RXHASH; + dev->features |=3D NETIF_F_RXHASH; + } + /* * Pretend we are using VLANs; This bypasses a nasty bug where * Interrupts stop flowing on high load on 8110SCd controllers. --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 CFA4E376BE4; Mon, 20 Apr 2026 02:20:55 +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=1776651658; cv=none; b=H1KWjnT00+Jk125DZvDP2mSm9OCzDQYEEGOurdM5vcL4uOs0/mRBEBlNLazRxb9r7Z+chpnjgpC+rsC8e4sEM21C7m5llDoYSH6KUIFF64oY/1Qo/XHWnGEh3vF4xjOqdBRTllNi+MFaOGbXkdWPd6vjUvI5I1C7aty5NbBUn+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651658; c=relaxed/simple; bh=1wZQ3t9NfE6/sECQRrmQQyt4rS356oBCKyv4IVG0HWk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JQqQMZXYc91wUGSXfa2RzY6vUSCVlArc9vzBp5xcGjdQTiYq0dZNVvOH0DV3VKyh4IlY2otFxJCDRItDitdZ6DBBfhmsPnrLcrg5yDfMHpbOCNd5RqwB3g0Mo+pZqIYLD15G29HlraYCC74l3WZU/ndoxukAy7pRyubADVWKYrU= 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=QUOmsics; 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="QUOmsics" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KFBn8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651615; bh=15jZdMzLqL1r1J17AOtoR/ouEzGiDYEmzXFKspDMQ4Y=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=QUOmsics5mps8qiISOVdLHNvneoHx+XiLNF+nWK874Dvvbdg7QhJlegk3P84k+0ek crWxluKahv3ipZK7fymV+wlgYHkV6kTnIsCq/kPlDXskIsJAqkQtCHVaFHD4UbeyEi TZ6iVXxAc6/s2sD1J4qK7UlV7cLNLJ+K3Ww1oUxTKOwwMKQLzlw2Qp7HQTbxdHgB5G dDZKmxaz3E8Tk9CsPR8mHyevwmjY/cR0uahXswXVxqwWkd1P00jGVQnldoM4InBPUj VNPeuCaMXbyJrzD7V6VypeaY+EcpIhDURNKuDqKlJBst9zbQQkzwVDuwy4gY65jV5L O/hyvFu8bZQfw== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KFBn8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:15 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:14 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:14 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 8/9] r8169: move struct ethtool_ops Date: Mon, 20 Apr 2026 10:19:56 +0800 Message-ID: <20260420021957.1756-9-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch move struct ethtool_ops, no changes. Prepare for next patch. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 56 +++++++++++------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index b3f15e6fd5e9..6b574fc336d6 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -2587,34 +2587,6 @@ static int rtl8169_set_link_ksettings(struct net_dev= ice *ndev, return 0; } =20 -static const struct ethtool_ops rtl8169_ethtool_ops =3D { - .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_MAX_FRAMES, - .get_drvinfo =3D rtl8169_get_drvinfo, - .get_regs_len =3D rtl8169_get_regs_len, - .get_link =3D ethtool_op_get_link, - .get_coalesce =3D rtl_get_coalesce, - .set_coalesce =3D rtl_set_coalesce, - .get_regs =3D rtl8169_get_regs, - .get_wol =3D rtl8169_get_wol, - .set_wol =3D rtl8169_set_wol, - .get_strings =3D rtl8169_get_strings, - .get_sset_count =3D rtl8169_get_sset_count, - .get_ethtool_stats =3D rtl8169_get_ethtool_stats, - .get_ts_info =3D ethtool_op_get_ts_info, - .nway_reset =3D phy_ethtool_nway_reset, - .get_eee =3D rtl8169_get_eee, - .set_eee =3D rtl8169_set_eee, - .get_link_ksettings =3D phy_ethtool_get_link_ksettings, - .set_link_ksettings =3D rtl8169_set_link_ksettings, - .get_ringparam =3D rtl8169_get_ringparam, - .get_pause_stats =3D rtl8169_get_pause_stats, - .get_pauseparam =3D rtl8169_get_pauseparam, - .set_pauseparam =3D rtl8169_set_pauseparam, - .get_eth_mac_stats =3D rtl8169_get_eth_mac_stats, - .get_eth_ctrl_stats =3D rtl8169_get_eth_ctrl_stats, -}; - static const struct rtl_chip_info *rtl8169_get_chip_version(u32 xid, bool = gmii) { /* Chips combining a 1Gbps MAC with a 100Mbps PHY */ @@ -6546,6 +6518,34 @@ static void r8169_init_napi(struct rtl8169_private *= tp) } } =20 +static const struct ethtool_ops rtl8169_ethtool_ops =3D { + .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_MAX_FRAMES, + .get_drvinfo =3D rtl8169_get_drvinfo, + .get_regs_len =3D rtl8169_get_regs_len, + .get_link =3D ethtool_op_get_link, + .get_coalesce =3D rtl_get_coalesce, + .set_coalesce =3D rtl_set_coalesce, + .get_regs =3D rtl8169_get_regs, + .get_wol =3D rtl8169_get_wol, + .set_wol =3D rtl8169_set_wol, + .get_strings =3D rtl8169_get_strings, + .get_sset_count =3D rtl8169_get_sset_count, + .get_ethtool_stats =3D rtl8169_get_ethtool_stats, + .get_ts_info =3D ethtool_op_get_ts_info, + .nway_reset =3D phy_ethtool_nway_reset, + .get_eee =3D rtl8169_get_eee, + .set_eee =3D rtl8169_set_eee, + .get_link_ksettings =3D phy_ethtool_get_link_ksettings, + .set_link_ksettings =3D rtl8169_set_link_ksettings, + .get_ringparam =3D rtl8169_get_ringparam, + .get_pause_stats =3D rtl8169_get_pause_stats, + .get_pauseparam =3D rtl8169_get_pauseparam, + .set_pauseparam =3D rtl8169_set_pauseparam, + .get_eth_mac_stats =3D rtl8169_get_eth_mac_stats, + .get_eth_ctrl_stats =3D rtl8169_get_eth_ctrl_stats, +}; + static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *= ent) { const struct rtl_chip_info *chip; --=20 2.43.0 From nobody Tue Jun 16 12:47:53 2026 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 96D3F3019D6; Mon, 20 Apr 2026 02:20:55 +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=1776651658; cv=none; b=mww0A96NtylLqg5VAozbh9Sny/WjlaXKxu41HOq2LaSM/azOUgwin7ppv7RA9oe5gYFlmJEyg1HFA6Jx4OS9RPLtNLbejlJRGo2w0BKmfZLwM2GGjSV/pwF7Rd3Xk1K/Y9khKnOfosNkiOpiW572hBBSMUySd/NJZVV/HDFn5Os= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776651658; c=relaxed/simple; bh=ePze4zJ1Uk9m0WMzKuVyeHySU7hMX6g5CuvVMBWSnck=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=e2+eNSZd7p6x4ueAn92WumT6aQF56jtkMlRdTPMYJZsCePy95DtODFFi5i3SEiBSE8tl2JLu/bWP6HB91q0tkWhOwWsOYssA8WIsKEwe7POjh9I0p2rD2EC4fy52ZrRzP/0GCwbElYL1Z47zh+bd/sEDXL7iJd5V17usYy9jg88= 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=VMbPPDfc; 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="VMbPPDfc" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 63K2KFBo8277433, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realsil.com.cn; s=dkim; t=1776651616; bh=lCnJ0HzsmVanHdXoXYyB2eK67+h1t5JXKZg5w4gYH88=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=VMbPPDfcyyLs9JetwuNU5ifsUt2+8R6JLiZkDygoV/fNCXLfO3RAVbnH2y0wTU9Rz AJ1xbPAd38hM8xuxuh+sAEkPZLQtC7XovTzyfZjiTOvGv6s7qQDiszPjVm+rFNuMpM DGemU3QKlJ+It7Ia+orircl6gYXqVvYF6o38Srmg2OlHBXuTYyKmEaTPjt6LvxXP5f 2qkfuDjukvyGTnMiflhSc4T5frsZlSQ/b+JrfG/hyFNR796y30/QcgopcyqJbNRn5h i4hlOekwiKGob3BIwarz3hzoe/2KJqQ3mwDTGzVKS1iLrKhE3joZ31k+uqSE/KHG3O bkYCr55zRQ7wA== Received: from RS-EX-MBS3.realsil.com.cn ([172.29.17.103]) by rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 63K2KFBo8277433 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 20 Apr 2026 10:20:15 +0800 Received: from RS-EX-MBS1.realsil.com.cn (172.29.17.101) by RS-EX-MBS3.realsil.com.cn (172.29.17.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 20 Apr 2026 10:20:14 +0800 Received: from 172.29.37.154 (172.29.37.152) by RS-EX-MBS1.realsil.com.cn (172.29.17.101) with Microsoft SMTP Server id 15.2.1748.39 via Frontend Transport; Mon, 20 Apr 2026 10:20:14 +0800 From: javen To: , , , , , , , CC: , , Javen Xu Subject: [RFC Patch net-next v1 9/9] r8169: add support for ethtool Date: Mon, 20 Apr 2026 10:19:57 +0800 Message-ID: <20260420021957.1756-10-javen_xu@realsil.com.cn> X-Mailer: git-send-email 2.50.1.windows.1 In-Reply-To: <20260420021957.1756-1-javen_xu@realsil.com.cn> References: <20260420021957.1756-1-javen_xu@realsil.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Javen Xu This patch add support for changing rx queues by ethtool. We can set rx 1, 2, 4, 8 by ethtool -L eth1 rx num. Signed-off-by: Javen Xu Tested-by: FUKAUMI Naoki --- drivers/net/ethernet/realtek/r8169_main.c | 68 +++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethern= et/realtek/r8169_main.c index 6b574fc336d6..57087abe7d88 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -6518,6 +6518,72 @@ static void r8169_init_napi(struct rtl8169_private *= tp) } } =20 +static void rtl8169_get_channels(struct net_device *dev, + struct ethtool_channels *ch) +{ + struct rtl8169_private *tp =3D netdev_priv(dev); + + ch->max_rx =3D tp->HwSuppNumRxQueues ? tp->HwSuppNumRxQueues : 1; + ch->max_tx =3D tp->HwSuppNumTxQueues ? tp->HwSuppNumTxQueues : 1; + ch->max_other =3D 0; + ch->max_combined =3D 0; + + ch->rx_count =3D tp->num_rx_rings; + ch->tx_count =3D tp->num_tx_rings; + ch->other_count =3D 0; + ch->combined_count =3D 0; +} + +static int rtl8169_set_channels(struct net_device *dev, + struct ethtool_channels *ch) +{ + struct rtl8169_private *tp =3D netdev_priv(dev); + bool if_running =3D netif_running(dev); + int i; + + if (!tp->rss_support && (ch->rx_count > 1 || ch->tx_count > 1)) { + netdev_warn(dev, "This chip does not support multiple channels/RSS.\n"); + return -EOPNOTSUPP; + } + + if (ch->rx_count =3D=3D 0 || ch->tx_count =3D=3D 0) + return -EINVAL; + if (ch->rx_count > tp->HwSuppNumRxQueues || + ch->tx_count > tp->HwSuppNumTxQueues) + return -EINVAL; + if (ch->other_count || ch->combined_count) + return -EINVAL; + + if (ch->rx_count =3D=3D tp->num_rx_rings && + ch->tx_count =3D=3D tp->num_tx_rings) + return 0; + + if (if_running) + rtl8169_close(dev); + + tp->num_rx_rings =3D ch->rx_count; + tp->num_tx_rings =3D ch->tx_count; + + tp->rss_enable =3D (tp->num_rx_rings > 1 && tp->rss_support); + + for (i =3D 0; i < tp->HwSuppIndirTblEntries; i++) { + if (tp->rss_enable) + tp->rss_indir_tbl[i] =3D ethtool_rxfh_indir_default(i, tp->num_rx_rings= ); + else + tp->rss_indir_tbl[i] =3D 0; + } + + if (tp->rss_enable) + tp->InitRxDescType =3D RX_DESC_RING_TYPE_RSS; + else + tp->InitRxDescType =3D RX_DESC_RING_TYPE_DEAFULT; + + if (if_running) + return rtl_open(dev); + + return 0; +} + static const struct ethtool_ops rtl8169_ethtool_ops =3D { .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES, @@ -6536,6 +6602,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = =3D { .nway_reset =3D phy_ethtool_nway_reset, .get_eee =3D rtl8169_get_eee, .set_eee =3D rtl8169_set_eee, + .get_channels =3D rtl8169_get_channels, + .set_channels =3D rtl8169_set_channels, .get_link_ksettings =3D phy_ethtool_get_link_ksettings, .set_link_ksettings =3D rtl8169_set_link_ksettings, .get_ringparam =3D rtl8169_get_ringparam, --=20 2.43.0