xref: /dpdk/drivers/net/r8169/r8169_ethdev.c (revision b574fb4cc855f4e86659d37ded01e7a218c38865)
19b170cfcSHoward Wang /* SPDX-License-Identifier: BSD-3-Clause
29b170cfcSHoward Wang  * Copyright(c) 2024 Realtek Corporation. All rights reserved
39b170cfcSHoward Wang  */
49b170cfcSHoward Wang 
59b170cfcSHoward Wang #include <stdio.h>
67d502791SHoward Wang #include <errno.h>
79b170cfcSHoward Wang #include <stdint.h>
89b170cfcSHoward Wang 
99b170cfcSHoward Wang #include <rte_eal.h>
109b170cfcSHoward Wang 
119b170cfcSHoward Wang #include <rte_common.h>
127d502791SHoward Wang #include <rte_interrupts.h>
137d502791SHoward Wang #include <rte_byteorder.h>
149b170cfcSHoward Wang #include <rte_pci.h>
159b170cfcSHoward Wang #include <bus_pci_driver.h>
169b170cfcSHoward Wang #include <rte_ether.h>
179b170cfcSHoward Wang #include <ethdev_driver.h>
189b170cfcSHoward Wang #include <ethdev_pci.h>
197d502791SHoward Wang #include <rte_memory.h>
207d502791SHoward Wang #include <rte_malloc.h>
219b170cfcSHoward Wang #include <dev_driver.h>
229b170cfcSHoward Wang 
239b170cfcSHoward Wang #include "r8169_ethdev.h"
249b170cfcSHoward Wang #include "r8169_compat.h"
251bbe869eSHoward Wang #include "r8169_logs.h"
261bbe869eSHoward Wang #include "r8169_hw.h"
27*b574fb4cSHoward Wang #include "r8169_dash.h"
289b170cfcSHoward Wang 
299b170cfcSHoward Wang static int rtl_dev_configure(struct rte_eth_dev *dev);
309b170cfcSHoward Wang static int rtl_dev_start(struct rte_eth_dev *dev);
319b170cfcSHoward Wang static int rtl_dev_stop(struct rte_eth_dev *dev);
329b170cfcSHoward Wang static int rtl_dev_reset(struct rte_eth_dev *dev);
339b170cfcSHoward Wang static int rtl_dev_close(struct rte_eth_dev *dev);
34f7327670SHoward Wang static int rtl_dev_link_update(struct rte_eth_dev *dev, int wait);
35f7327670SHoward Wang static int rtl_dev_set_link_up(struct rte_eth_dev *dev);
36f7327670SHoward Wang static int rtl_dev_set_link_down(struct rte_eth_dev *dev);
372f198f0aSHoward Wang static int rtl_dev_infos_get(struct rte_eth_dev *dev,
382f198f0aSHoward Wang 			     struct rte_eth_dev_info *dev_info);
39fa0b0ad6SHoward Wang static int rtl_dev_stats_get(struct rte_eth_dev *dev,
40fa0b0ad6SHoward Wang 			     struct rte_eth_stats *rte_stats);
41fa0b0ad6SHoward Wang static int rtl_dev_stats_reset(struct rte_eth_dev *dev);
42d2b39de2SHoward Wang static int rtl_promiscuous_enable(struct rte_eth_dev *dev);
43d2b39de2SHoward Wang static int rtl_promiscuous_disable(struct rte_eth_dev *dev);
44d2b39de2SHoward Wang static int rtl_allmulticast_enable(struct rte_eth_dev *dev);
45d2b39de2SHoward Wang static int rtl_allmulticast_disable(struct rte_eth_dev *dev);
469514e4b6SHoward Wang static int rtl_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
47b2e17252SHoward Wang static int rtl_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
48b2e17252SHoward Wang 			      size_t fw_size);
499b170cfcSHoward Wang 
509b170cfcSHoward Wang /*
519b170cfcSHoward Wang  * The set of PCI devices this driver supports
529b170cfcSHoward Wang  */
539b170cfcSHoward Wang static const struct rte_pci_id pci_id_r8169_map[] = {
549b170cfcSHoward Wang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125) },
559b170cfcSHoward Wang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8162) },
569b170cfcSHoward Wang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8126) },
579b170cfcSHoward Wang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5000) },
589b170cfcSHoward Wang 	{.vendor_id = 0, /* sentinel */ },
599b170cfcSHoward Wang };
609b170cfcSHoward Wang 
612f198f0aSHoward Wang static const struct rte_eth_desc_lim rx_desc_lim = {
622f198f0aSHoward Wang 	.nb_max   = RTL_MAX_RX_DESC,
632f198f0aSHoward Wang 	.nb_min   = RTL_MIN_RX_DESC,
642f198f0aSHoward Wang 	.nb_align = RTL_DESC_ALIGN,
652f198f0aSHoward Wang };
662f198f0aSHoward Wang 
672f198f0aSHoward Wang static const struct rte_eth_desc_lim tx_desc_lim = {
682f198f0aSHoward Wang 	.nb_max         = RTL_MAX_TX_DESC,
692f198f0aSHoward Wang 	.nb_min         = RTL_MIN_TX_DESC,
702f198f0aSHoward Wang 	.nb_align       = RTL_DESC_ALIGN,
712f198f0aSHoward Wang 	.nb_seg_max     = RTL_MAX_TX_SEG,
722f198f0aSHoward Wang 	.nb_mtu_seg_max = RTL_MAX_TX_SEG,
732f198f0aSHoward Wang };
742f198f0aSHoward Wang 
759b170cfcSHoward Wang static const struct eth_dev_ops rtl_eth_dev_ops = {
769b170cfcSHoward Wang 	.dev_configure	      = rtl_dev_configure,
779b170cfcSHoward Wang 	.dev_start	      = rtl_dev_start,
789b170cfcSHoward Wang 	.dev_stop	      = rtl_dev_stop,
799b170cfcSHoward Wang 	.dev_close	      = rtl_dev_close,
809b170cfcSHoward Wang 	.dev_reset	      = rtl_dev_reset,
81f7327670SHoward Wang 	.dev_set_link_up      = rtl_dev_set_link_up,
82f7327670SHoward Wang 	.dev_set_link_down    = rtl_dev_set_link_down,
832f198f0aSHoward Wang 	.dev_infos_get        = rtl_dev_infos_get,
84f7327670SHoward Wang 
85d2b39de2SHoward Wang 	.promiscuous_enable   = rtl_promiscuous_enable,
86d2b39de2SHoward Wang 	.promiscuous_disable  = rtl_promiscuous_disable,
87d2b39de2SHoward Wang 	.allmulticast_enable  = rtl_allmulticast_enable,
88d2b39de2SHoward Wang 	.allmulticast_disable = rtl_allmulticast_disable,
89d2b39de2SHoward Wang 
90f7327670SHoward Wang 	.link_update          = rtl_dev_link_update,
912f198f0aSHoward Wang 
92fa0b0ad6SHoward Wang 	.stats_get            = rtl_dev_stats_get,
93fa0b0ad6SHoward Wang 	.stats_reset          = rtl_dev_stats_reset,
94fa0b0ad6SHoward Wang 
959514e4b6SHoward Wang 	.mtu_set              = rtl_dev_mtu_set,
969514e4b6SHoward Wang 
97b2e17252SHoward Wang 	.fw_version_get       = rtl_fw_version_get,
98b2e17252SHoward Wang 
992f198f0aSHoward Wang 	.rx_queue_setup       = rtl_rx_queue_setup,
1002f198f0aSHoward Wang 	.rx_queue_release     = rtl_rx_queue_release,
1012f198f0aSHoward Wang 	.rxq_info_get         = rtl_rxq_info_get,
10263d37ff9SHoward Wang 
10363d37ff9SHoward Wang 	.tx_queue_setup       = rtl_tx_queue_setup,
10463d37ff9SHoward Wang 	.tx_queue_release     = rtl_tx_queue_release,
10563d37ff9SHoward Wang 	.tx_done_cleanup      = rtl_tx_done_cleanup,
10663d37ff9SHoward Wang 	.txq_info_get         = rtl_txq_info_get,
1079b170cfcSHoward Wang };
1089b170cfcSHoward Wang 
1099b170cfcSHoward Wang static int
1109b170cfcSHoward Wang rtl_dev_configure(struct rte_eth_dev *dev __rte_unused)
1119b170cfcSHoward Wang {
1129b170cfcSHoward Wang 	return 0;
1139b170cfcSHoward Wang }
1149b170cfcSHoward Wang 
115f7327670SHoward Wang static void
116f7327670SHoward Wang rtl_disable_intr(struct rtl_hw *hw)
117f7327670SHoward Wang {
118f7327670SHoward Wang 	PMD_INIT_FUNC_TRACE();
119f7327670SHoward Wang 	RTL_W32(hw, IMR0_8125, 0x0000);
120f7327670SHoward Wang 	RTL_W32(hw, ISR0_8125, RTL_R32(hw, ISR0_8125));
121f7327670SHoward Wang }
122f7327670SHoward Wang 
123f7327670SHoward Wang static void
124f7327670SHoward Wang rtl_enable_intr(struct rtl_hw *hw)
125f7327670SHoward Wang {
126f7327670SHoward Wang 	PMD_INIT_FUNC_TRACE();
127f7327670SHoward Wang 	RTL_W32(hw, IMR0_8125, LinkChg);
128f7327670SHoward Wang }
129f7327670SHoward Wang 
130f7327670SHoward Wang static int
131f7327670SHoward Wang _rtl_setup_link(struct rte_eth_dev *dev)
132f7327670SHoward Wang {
133f7327670SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
134f7327670SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
135f7327670SHoward Wang 	u64 adv = 0;
136f7327670SHoward Wang 	u32 *link_speeds = &dev->data->dev_conf.link_speeds;
137f7327670SHoward Wang 
138f7327670SHoward Wang 	/* Setup link speed and duplex */
139f7327670SHoward Wang 	if (*link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) {
140f7327670SHoward Wang 		rtl_set_link_option(hw, AUTONEG_ENABLE, SPEED_5000, DUPLEX_FULL, rtl_fc_full);
141f7327670SHoward Wang 	} else if (*link_speeds != 0) {
142f7327670SHoward Wang 		if (*link_speeds & ~(RTE_ETH_LINK_SPEED_10M_HD | RTE_ETH_LINK_SPEED_10M |
143f7327670SHoward Wang 				     RTE_ETH_LINK_SPEED_100M_HD | RTE_ETH_LINK_SPEED_100M |
144f7327670SHoward Wang 				     RTE_ETH_LINK_SPEED_1G | RTE_ETH_LINK_SPEED_2_5G |
145f7327670SHoward Wang 				     RTE_ETH_LINK_SPEED_5G | RTE_ETH_LINK_SPEED_FIXED))
146f7327670SHoward Wang 			goto error_invalid_config;
147f7327670SHoward Wang 
148f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_10M_HD) {
149f7327670SHoward Wang 			hw->speed = SPEED_10;
150f7327670SHoward Wang 			hw->duplex = DUPLEX_HALF;
151f7327670SHoward Wang 			adv |= ADVERTISE_10_HALF;
152f7327670SHoward Wang 		}
153f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_10M) {
154f7327670SHoward Wang 			hw->speed = SPEED_10;
155f7327670SHoward Wang 			hw->duplex = DUPLEX_FULL;
156f7327670SHoward Wang 			adv |= ADVERTISE_10_FULL;
157f7327670SHoward Wang 		}
158f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_100M_HD) {
159f7327670SHoward Wang 			hw->speed = SPEED_100;
160f7327670SHoward Wang 			hw->duplex = DUPLEX_HALF;
161f7327670SHoward Wang 			adv |= ADVERTISE_100_HALF;
162f7327670SHoward Wang 		}
163f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_100M) {
164f7327670SHoward Wang 			hw->speed = SPEED_100;
165f7327670SHoward Wang 			hw->duplex = DUPLEX_FULL;
166f7327670SHoward Wang 			adv |= ADVERTISE_100_FULL;
167f7327670SHoward Wang 		}
168f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_1G) {
169f7327670SHoward Wang 			hw->speed = SPEED_1000;
170f7327670SHoward Wang 			hw->duplex = DUPLEX_FULL;
171f7327670SHoward Wang 			adv |= ADVERTISE_1000_FULL;
172f7327670SHoward Wang 		}
173f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_2_5G) {
174f7327670SHoward Wang 			hw->speed = SPEED_2500;
175f7327670SHoward Wang 			hw->duplex = DUPLEX_FULL;
176f7327670SHoward Wang 			adv |= ADVERTISE_2500_FULL;
177f7327670SHoward Wang 		}
178f7327670SHoward Wang 		if (*link_speeds & RTE_ETH_LINK_SPEED_5G) {
179f7327670SHoward Wang 			hw->speed = SPEED_5000;
180f7327670SHoward Wang 			hw->duplex = DUPLEX_FULL;
181f7327670SHoward Wang 			adv |= ADVERTISE_5000_FULL;
182f7327670SHoward Wang 		}
183f7327670SHoward Wang 
184f7327670SHoward Wang 		hw->autoneg = AUTONEG_ENABLE;
185f7327670SHoward Wang 		hw->advertising = adv;
186f7327670SHoward Wang 	}
187f7327670SHoward Wang 
188f7327670SHoward Wang 	rtl_set_speed(hw);
189f7327670SHoward Wang 
190f7327670SHoward Wang 	return 0;
191f7327670SHoward Wang 
192f7327670SHoward Wang error_invalid_config:
193f7327670SHoward Wang 	PMD_INIT_LOG(ERR, "Invalid advertised speeds (%u) for port %u",
194f7327670SHoward Wang 		     dev->data->dev_conf.link_speeds, dev->data->port_id);
1952f198f0aSHoward Wang 	rtl_stop_queues(dev);
196f7327670SHoward Wang 	return -EINVAL;
197f7327670SHoward Wang }
198f7327670SHoward Wang 
199f7327670SHoward Wang static int
200f7327670SHoward Wang rtl_setup_link(struct rte_eth_dev *dev)
201f7327670SHoward Wang {
202f7327670SHoward Wang #ifdef RTE_EXEC_ENV_FREEBSD
203f7327670SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
204f7327670SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
205f7327670SHoward Wang 	struct rte_eth_link link;
206f7327670SHoward Wang 	int count;
207f7327670SHoward Wang #endif
208f7327670SHoward Wang 
209f7327670SHoward Wang 	_rtl_setup_link(dev);
210f7327670SHoward Wang 
211f7327670SHoward Wang #ifdef RTE_EXEC_ENV_FREEBSD
212f7327670SHoward Wang 	for (count = 0; count < R8169_LINK_CHECK_TIMEOUT; count++) {
213f7327670SHoward Wang 		if (!(RTL_R16(hw, PHYstatus) & LinkStatus)) {
214f7327670SHoward Wang 			rte_delay_ms(R8169_LINK_CHECK_INTERVAL);
215f7327670SHoward Wang 			continue;
216f7327670SHoward Wang 		}
217f7327670SHoward Wang 
218f7327670SHoward Wang 		rtl_dev_link_update(dev, 0);
219f7327670SHoward Wang 
220f7327670SHoward Wang 		rte_eth_linkstatus_get(dev, &link);
221f7327670SHoward Wang 
222f7327670SHoward Wang 		return 0;
223f7327670SHoward Wang 	}
224f7327670SHoward Wang #endif
225f7327670SHoward Wang 	return 0;
226f7327670SHoward Wang }
227f7327670SHoward Wang 
2289b170cfcSHoward Wang /*
2299b170cfcSHoward Wang  * Configure device link speed and setup link.
2309b170cfcSHoward Wang  * It returns 0 on success.
2319b170cfcSHoward Wang  */
2329b170cfcSHoward Wang static int
2331bbe869eSHoward Wang rtl_dev_start(struct rte_eth_dev *dev)
2349b170cfcSHoward Wang {
235619f6ebcSHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
236619f6ebcSHoward Wang 	struct rtl_hw *hw = &adapter->hw;
237f7327670SHoward Wang 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
238f7327670SHoward Wang 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
2391bbe869eSHoward Wang 	int err;
2401bbe869eSHoward Wang 
241f7327670SHoward Wang 	/* Disable uio/vfio intr/eventfd mapping */
242f7327670SHoward Wang 	rte_intr_disable(intr_handle);
243f7327670SHoward Wang 
24438589978SHoward Wang 	rtl_powerup_pll(hw);
24538589978SHoward Wang 
24638589978SHoward Wang 	rtl_hw_ephy_config(hw);
24738589978SHoward Wang 
24838589978SHoward Wang 	rtl_hw_phy_config(hw);
24938589978SHoward Wang 
250619f6ebcSHoward Wang 	rtl_hw_config(hw);
251619f6ebcSHoward Wang 
2521bbe869eSHoward Wang 	/* Initialize transmission unit */
2531bbe869eSHoward Wang 	rtl_tx_init(dev);
2541bbe869eSHoward Wang 
2551bbe869eSHoward Wang 	/* This can fail when allocating mbufs for descriptor rings */
2561bbe869eSHoward Wang 	err = rtl_rx_init(dev);
2571bbe869eSHoward Wang 	if (err) {
2581bbe869eSHoward Wang 		PMD_INIT_LOG(ERR, "Unable to initialize RX hardware");
2591bbe869eSHoward Wang 		goto error;
2601bbe869eSHoward Wang 	}
2611bbe869eSHoward Wang 
262fa0b0ad6SHoward Wang 	/* This can fail when allocating mem for tally counters */
263fa0b0ad6SHoward Wang 	err = rtl_tally_init(dev);
264fa0b0ad6SHoward Wang 	if (err)
265fa0b0ad6SHoward Wang 		goto error;
266fa0b0ad6SHoward Wang 
267f7327670SHoward Wang 	/* Enable uio/vfio intr/eventfd mapping */
268f7327670SHoward Wang 	rte_intr_enable(intr_handle);
269f7327670SHoward Wang 
270f7327670SHoward Wang 	/* Resume enabled intr since hw reset */
271f7327670SHoward Wang 	rtl_enable_intr(hw);
272f7327670SHoward Wang 
273f7327670SHoward Wang 	rtl_setup_link(dev);
274f7327670SHoward Wang 
27538589978SHoward Wang 	rtl_mdio_write(hw, 0x1F, 0x0000);
27638589978SHoward Wang 
2779b170cfcSHoward Wang 	return 0;
2781bbe869eSHoward Wang error:
2792f198f0aSHoward Wang 	rtl_stop_queues(dev);
2801bbe869eSHoward Wang 	return -EIO;
2819b170cfcSHoward Wang }
2829b170cfcSHoward Wang 
2839b170cfcSHoward Wang /*
2849b170cfcSHoward Wang  * Stop device: disable RX and TX functions to allow for reconfiguring.
2859b170cfcSHoward Wang  */
2869b170cfcSHoward Wang static int
28738589978SHoward Wang rtl_dev_stop(struct rte_eth_dev *dev)
2889b170cfcSHoward Wang {
28938589978SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
29038589978SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
291f7327670SHoward Wang 	struct rte_eth_link link;
292f7327670SHoward Wang 
293f7327670SHoward Wang 	rtl_disable_intr(hw);
29438589978SHoward Wang 
2957d502791SHoward Wang 	rtl_nic_reset(hw);
2967d502791SHoward Wang 
2977d502791SHoward Wang 	switch (hw->mcfg) {
2987d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
2997d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
3007d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xE00A, hw->mcu_pme_setting);
3017d502791SHoward Wang 		break;
3027d502791SHoward Wang 	}
3037d502791SHoward Wang 
30438589978SHoward Wang 	rtl_powerdown_pll(hw);
30538589978SHoward Wang 
3062f198f0aSHoward Wang 	rtl_stop_queues(dev);
3072f198f0aSHoward Wang 
308fa0b0ad6SHoward Wang 	rtl_tally_free(dev);
309fa0b0ad6SHoward Wang 
310f7327670SHoward Wang 	/* Clear the recorded link status */
311f7327670SHoward Wang 	memset(&link, 0, sizeof(link));
312f7327670SHoward Wang 	rte_eth_linkstatus_set(dev, &link);
313f7327670SHoward Wang 
3149b170cfcSHoward Wang 	return 0;
3159b170cfcSHoward Wang }
3169b170cfcSHoward Wang 
317f7327670SHoward Wang static int
318f7327670SHoward Wang rtl_dev_set_link_up(struct rte_eth_dev *dev)
319f7327670SHoward Wang {
320f7327670SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
321f7327670SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
322f7327670SHoward Wang 
323f7327670SHoward Wang 	rtl_powerup_pll(hw);
324f7327670SHoward Wang 
325f7327670SHoward Wang 	return 0;
326f7327670SHoward Wang }
327f7327670SHoward Wang 
328f7327670SHoward Wang static int
329f7327670SHoward Wang rtl_dev_set_link_down(struct rte_eth_dev *dev)
330f7327670SHoward Wang {
331f7327670SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
332f7327670SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
333f7327670SHoward Wang 
334f7327670SHoward Wang 	/* mcu pme intr masks */
335f7327670SHoward Wang 	switch (hw->mcfg) {
336f7327670SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
337f7327670SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
338f7327670SHoward Wang 		rtl_mac_ocp_write(hw, 0xE00A, hw->mcu_pme_setting & ~(BIT_11 | BIT_14));
339f7327670SHoward Wang 		break;
340f7327670SHoward Wang 	}
341f7327670SHoward Wang 
342f7327670SHoward Wang 	rtl_powerdown_pll(hw);
343f7327670SHoward Wang 
344f7327670SHoward Wang 	return 0;
345f7327670SHoward Wang }
346f7327670SHoward Wang 
3472f198f0aSHoward Wang static int
3482f198f0aSHoward Wang rtl_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
3492f198f0aSHoward Wang {
3502f198f0aSHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
3512f198f0aSHoward Wang 	struct rtl_hw *hw = &adapter->hw;
3522f198f0aSHoward Wang 
3532f198f0aSHoward Wang 	dev_info->min_rx_bufsize = 1024;
3542f198f0aSHoward Wang 	dev_info->max_rx_pktlen = JUMBO_FRAME_9K;
3552f198f0aSHoward Wang 	dev_info->max_mac_addrs = 1;
3562f198f0aSHoward Wang 
3572f198f0aSHoward Wang 	dev_info->max_rx_queues = 1;
3582f198f0aSHoward Wang 	dev_info->max_tx_queues = 1;
3592f198f0aSHoward Wang 
3602f198f0aSHoward Wang 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
3612f198f0aSHoward Wang 		.rx_free_thresh = RTL_RX_FREE_THRESH,
3622f198f0aSHoward Wang 	};
3632f198f0aSHoward Wang 
3642f198f0aSHoward Wang 	dev_info->default_txconf = (struct rte_eth_txconf) {
3652f198f0aSHoward Wang 		.tx_free_thresh = RTL_TX_FREE_THRESH,
3662f198f0aSHoward Wang 	};
3672f198f0aSHoward Wang 
3682f198f0aSHoward Wang 	dev_info->rx_desc_lim = rx_desc_lim;
3692f198f0aSHoward Wang 	dev_info->tx_desc_lim = tx_desc_lim;
3702f198f0aSHoward Wang 
3712f198f0aSHoward Wang 	dev_info->speed_capa = RTE_ETH_LINK_SPEED_10M_HD | RTE_ETH_LINK_SPEED_10M |
3722f198f0aSHoward Wang 			       RTE_ETH_LINK_SPEED_100M_HD | RTE_ETH_LINK_SPEED_100M |
3732f198f0aSHoward Wang 			       RTE_ETH_LINK_SPEED_1G;
3742f198f0aSHoward Wang 
3752f198f0aSHoward Wang 	switch (hw->chipset_name) {
3762f198f0aSHoward Wang 	case RTL8126A:
3772f198f0aSHoward Wang 		dev_info->speed_capa |= RTE_ETH_LINK_SPEED_5G;
3782f198f0aSHoward Wang 	/* fallthrough */
3792f198f0aSHoward Wang 	case RTL8125A:
3802f198f0aSHoward Wang 	case RTL8125B:
3812f198f0aSHoward Wang 		dev_info->speed_capa |= RTE_ETH_LINK_SPEED_2_5G;
3822f198f0aSHoward Wang 		break;
3832f198f0aSHoward Wang 	}
3842f198f0aSHoward Wang 
3859514e4b6SHoward Wang 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
3869514e4b6SHoward Wang 	dev_info->max_mtu = dev_info->max_rx_pktlen - RTL_ETH_OVERHEAD;
3879514e4b6SHoward Wang 
3882f198f0aSHoward Wang 	dev_info->rx_offload_capa = (rtl_get_rx_port_offloads() |
3892f198f0aSHoward Wang 				     dev_info->rx_queue_offload_capa);
39063d37ff9SHoward Wang 	dev_info->tx_offload_capa = rtl_get_tx_port_offloads();
3912f198f0aSHoward Wang 
3922f198f0aSHoward Wang 	return 0;
3932f198f0aSHoward Wang }
3942f198f0aSHoward Wang 
395fa0b0ad6SHoward Wang static int
396d2b39de2SHoward Wang rtl_promiscuous_enable(struct rte_eth_dev *dev)
397d2b39de2SHoward Wang {
398d2b39de2SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
399d2b39de2SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
400d2b39de2SHoward Wang 
401d2b39de2SHoward Wang 	int rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys;
402d2b39de2SHoward Wang 
403d2b39de2SHoward Wang 	RTL_W32(hw, RxConfig, rx_mode | (RTL_R32(hw, RxConfig)));
404d2b39de2SHoward Wang 	rtl_allmulticast_enable(dev);
405d2b39de2SHoward Wang 
406d2b39de2SHoward Wang 	return 0;
407d2b39de2SHoward Wang }
408d2b39de2SHoward Wang 
409d2b39de2SHoward Wang static int
410d2b39de2SHoward Wang rtl_promiscuous_disable(struct rte_eth_dev *dev)
411d2b39de2SHoward Wang {
412d2b39de2SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
413d2b39de2SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
414d2b39de2SHoward Wang 	int rx_mode = ~AcceptAllPhys;
415d2b39de2SHoward Wang 
416d2b39de2SHoward Wang 	RTL_W32(hw, RxConfig, rx_mode & (RTL_R32(hw, RxConfig)));
417d2b39de2SHoward Wang 
418d2b39de2SHoward Wang 	if (dev->data->all_multicast == 1)
419d2b39de2SHoward Wang 		rtl_allmulticast_enable(dev);
420d2b39de2SHoward Wang 	else
421d2b39de2SHoward Wang 		rtl_allmulticast_disable(dev);
422d2b39de2SHoward Wang 
423d2b39de2SHoward Wang 	return 0;
424d2b39de2SHoward Wang }
425d2b39de2SHoward Wang 
426d2b39de2SHoward Wang static int
427d2b39de2SHoward Wang rtl_allmulticast_enable(struct rte_eth_dev *dev)
428d2b39de2SHoward Wang {
429d2b39de2SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
430d2b39de2SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
431d2b39de2SHoward Wang 
432d2b39de2SHoward Wang 	RTL_W32(hw, MAR0 + 0, 0xffffffff);
433d2b39de2SHoward Wang 	RTL_W32(hw, MAR0 + 4, 0xffffffff);
434d2b39de2SHoward Wang 
435d2b39de2SHoward Wang 	return 0;
436d2b39de2SHoward Wang }
437d2b39de2SHoward Wang 
438d2b39de2SHoward Wang static int
439d2b39de2SHoward Wang rtl_allmulticast_disable(struct rte_eth_dev *dev)
440d2b39de2SHoward Wang {
441d2b39de2SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
442d2b39de2SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
443d2b39de2SHoward Wang 
444d2b39de2SHoward Wang 	if (dev->data->promiscuous == 1)
445d2b39de2SHoward Wang 		return 0; /* Must remain in all_multicast mode */
446d2b39de2SHoward Wang 
447d2b39de2SHoward Wang 	RTL_W32(hw, MAR0 + 0, 0);
448d2b39de2SHoward Wang 	RTL_W32(hw, MAR0 + 4, 0);
449d2b39de2SHoward Wang 
450d2b39de2SHoward Wang 	return 0;
451d2b39de2SHoward Wang }
452d2b39de2SHoward Wang 
453d2b39de2SHoward Wang static int
454fa0b0ad6SHoward Wang rtl_dev_stats_reset(struct rte_eth_dev *dev)
455fa0b0ad6SHoward Wang {
456fa0b0ad6SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
457fa0b0ad6SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
458fa0b0ad6SHoward Wang 
459fa0b0ad6SHoward Wang 	rtl_clear_tally_stats(hw);
460fa0b0ad6SHoward Wang 
461fa0b0ad6SHoward Wang 	memset(&adapter->sw_stats, 0, sizeof(adapter->sw_stats));
462fa0b0ad6SHoward Wang 
463fa0b0ad6SHoward Wang 	return 0;
464fa0b0ad6SHoward Wang }
465fa0b0ad6SHoward Wang 
466fa0b0ad6SHoward Wang static void
467fa0b0ad6SHoward Wang rtl_sw_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
468fa0b0ad6SHoward Wang {
469fa0b0ad6SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
470fa0b0ad6SHoward Wang 	struct rtl_sw_stats *sw_stats = &adapter->sw_stats;
471fa0b0ad6SHoward Wang 
472fa0b0ad6SHoward Wang 	rte_stats->ibytes = sw_stats->rx_bytes;
473fa0b0ad6SHoward Wang 	rte_stats->obytes = sw_stats->tx_bytes;
474fa0b0ad6SHoward Wang }
475fa0b0ad6SHoward Wang 
476fa0b0ad6SHoward Wang static int
477fa0b0ad6SHoward Wang rtl_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
478fa0b0ad6SHoward Wang {
479fa0b0ad6SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
480fa0b0ad6SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
481fa0b0ad6SHoward Wang 
482fa0b0ad6SHoward Wang 	rtl_get_tally_stats(hw, rte_stats);
483fa0b0ad6SHoward Wang 	rtl_sw_stats_get(dev, rte_stats);
484fa0b0ad6SHoward Wang 
485fa0b0ad6SHoward Wang 	return 0;
486fa0b0ad6SHoward Wang }
487fa0b0ad6SHoward Wang 
488f7327670SHoward Wang /* Return 0 means link status changed, -1 means not changed */
489f7327670SHoward Wang static int
490f7327670SHoward Wang rtl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused)
491f7327670SHoward Wang {
492f7327670SHoward Wang 	struct rte_eth_link link, old;
493f7327670SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
494f7327670SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
495f7327670SHoward Wang 	u32 speed;
496f7327670SHoward Wang 	u16 status;
497f7327670SHoward Wang 
498f7327670SHoward Wang 	link.link_status = RTE_ETH_LINK_DOWN;
499f7327670SHoward Wang 	link.link_speed = 0;
500f7327670SHoward Wang 	link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
501f7327670SHoward Wang 	link.link_autoneg = RTE_ETH_LINK_AUTONEG;
502f7327670SHoward Wang 
503f7327670SHoward Wang 	memset(&old, 0, sizeof(old));
504f7327670SHoward Wang 
505f7327670SHoward Wang 	/* Load old link status */
506f7327670SHoward Wang 	rte_eth_linkstatus_get(dev, &old);
507f7327670SHoward Wang 
508f7327670SHoward Wang 	/* Read current link status */
509f7327670SHoward Wang 	status = RTL_R16(hw, PHYstatus);
510f7327670SHoward Wang 
511f7327670SHoward Wang 	if (status & LinkStatus) {
512f7327670SHoward Wang 		link.link_status = RTE_ETH_LINK_UP;
513f7327670SHoward Wang 
514f7327670SHoward Wang 		if (status & FullDup) {
515f7327670SHoward Wang 			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
516f7327670SHoward Wang 			if (hw->mcfg == CFG_METHOD_2)
517f7327670SHoward Wang 				RTL_W32(hw, TxConfig, (RTL_R32(hw, TxConfig) |
518f7327670SHoward Wang 						       (BIT_24 | BIT_25)) & ~BIT_19);
519f7327670SHoward Wang 
520f7327670SHoward Wang 		} else {
521f7327670SHoward Wang 			link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
522f7327670SHoward Wang 			if (hw->mcfg == CFG_METHOD_2)
523f7327670SHoward Wang 				RTL_W32(hw, TxConfig, (RTL_R32(hw, TxConfig) | BIT_25) &
524f7327670SHoward Wang 					~(BIT_19 | BIT_24));
525f7327670SHoward Wang 		}
526f7327670SHoward Wang 
527f7327670SHoward Wang 		if (status & _5000bpsF)
528f7327670SHoward Wang 			speed = 5000;
529f7327670SHoward Wang 		else if (status & _2500bpsF)
530f7327670SHoward Wang 			speed = 2500;
531f7327670SHoward Wang 		else if (status & _1000bpsF)
532f7327670SHoward Wang 			speed = 1000;
533f7327670SHoward Wang 		else if (status & _100bps)
534f7327670SHoward Wang 			speed = 100;
535f7327670SHoward Wang 		else
536f7327670SHoward Wang 			speed = 10;
537f7327670SHoward Wang 
538f7327670SHoward Wang 		link.link_speed = speed;
539f7327670SHoward Wang 	}
540f7327670SHoward Wang 
541f7327670SHoward Wang 	if (link.link_status == old.link_status)
542f7327670SHoward Wang 		return -1;
543f7327670SHoward Wang 
544f7327670SHoward Wang 	rte_eth_linkstatus_set(dev, &link);
545f7327670SHoward Wang 
546f7327670SHoward Wang 	return 0;
547f7327670SHoward Wang }
548f7327670SHoward Wang 
549f7327670SHoward Wang static void
550f7327670SHoward Wang rtl_dev_interrupt_handler(void *param)
551f7327670SHoward Wang {
552f7327670SHoward Wang 	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
553f7327670SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
554f7327670SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
555f7327670SHoward Wang 	uint32_t intr;
556f7327670SHoward Wang 
557f7327670SHoward Wang 	intr = RTL_R32(hw, ISR0_8125);
558f7327670SHoward Wang 
559f7327670SHoward Wang 	/* Clear all cause mask */
560f7327670SHoward Wang 	rtl_disable_intr(hw);
561f7327670SHoward Wang 
562f7327670SHoward Wang 	if (intr & LinkChg)
563f7327670SHoward Wang 		rtl_dev_link_update(dev, 0);
564f7327670SHoward Wang 	else
565f7327670SHoward Wang 		PMD_DRV_LOG(ERR, "r8169: interrupt unhandled.");
566f7327670SHoward Wang 
567f7327670SHoward Wang 	rtl_enable_intr(hw);
568f7327670SHoward Wang }
569f7327670SHoward Wang 
5709b170cfcSHoward Wang /*
5719b170cfcSHoward Wang  * Reset and stop device.
5729b170cfcSHoward Wang  */
5739b170cfcSHoward Wang static int
5749b170cfcSHoward Wang rtl_dev_close(struct rte_eth_dev *dev)
5759b170cfcSHoward Wang {
576f7327670SHoward Wang 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
577f7327670SHoward Wang 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
5787d502791SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
5797d502791SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
580f7327670SHoward Wang 	int retries = 0;
581f7327670SHoward Wang 	int ret_unreg, ret_stp;
5829b170cfcSHoward Wang 
5839b170cfcSHoward Wang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5849b170cfcSHoward Wang 		return 0;
5859b170cfcSHoward Wang 
586*b574fb4cSHoward Wang 	if (HW_DASH_SUPPORT_DASH(hw))
587*b574fb4cSHoward Wang 		rtl8125_driver_stop(hw);
588*b574fb4cSHoward Wang 
5899b170cfcSHoward Wang 	ret_stp = rtl_dev_stop(dev);
5909b170cfcSHoward Wang 
5912f198f0aSHoward Wang 	rtl_free_queues(dev);
5922f198f0aSHoward Wang 
5937d502791SHoward Wang 	/* Reprogram the RAR[0] in case user changed it. */
5947d502791SHoward Wang 	rtl_rar_set(hw, hw->mac_addr);
5957d502791SHoward Wang 
596f7327670SHoward Wang 	/* Disable uio intr before callback unregister */
597f7327670SHoward Wang 	rte_intr_disable(intr_handle);
598f7327670SHoward Wang 
599f7327670SHoward Wang 	do {
600f7327670SHoward Wang 		ret_unreg = rte_intr_callback_unregister(intr_handle, rtl_dev_interrupt_handler,
601f7327670SHoward Wang 							 dev);
602f7327670SHoward Wang 		if (ret_unreg >= 0 || ret_unreg == -ENOENT)
603f7327670SHoward Wang 			break;
604f7327670SHoward Wang 		else if (ret_unreg != -EAGAIN)
605f7327670SHoward Wang 			PMD_DRV_LOG(ERR, "r8169: intr callback unregister failed: %d", ret_unreg);
606f7327670SHoward Wang 
607f7327670SHoward Wang 		rte_delay_ms(100);
608f7327670SHoward Wang 	} while (retries++ < (10 + 90));
609f7327670SHoward Wang 
6109b170cfcSHoward Wang 	return ret_stp;
6119b170cfcSHoward Wang }
6129b170cfcSHoward Wang 
6139b170cfcSHoward Wang static int
6149514e4b6SHoward Wang rtl_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
6159514e4b6SHoward Wang {
6169514e4b6SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
6179514e4b6SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
6189514e4b6SHoward Wang 	uint32_t frame_size = mtu + RTL_ETH_OVERHEAD;
6199514e4b6SHoward Wang 
6209514e4b6SHoward Wang 	hw->mtu = mtu;
6219514e4b6SHoward Wang 
6229514e4b6SHoward Wang 	RTL_W16(hw, RxMaxSize, frame_size);
6239514e4b6SHoward Wang 
6249514e4b6SHoward Wang 	return 0;
6259514e4b6SHoward Wang }
6269514e4b6SHoward Wang 
6279514e4b6SHoward Wang static int
628b2e17252SHoward Wang rtl_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
629b2e17252SHoward Wang {
630b2e17252SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
631b2e17252SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
632b2e17252SHoward Wang 	int ret;
633b2e17252SHoward Wang 
634b2e17252SHoward Wang 	ret = snprintf(fw_version, fw_size, "0x%08x", hw->hw_ram_code_ver);
635b2e17252SHoward Wang 
636b2e17252SHoward Wang 	ret += 1; /* Add the size of '\0' */
637b2e17252SHoward Wang 	if (fw_size < (u32)ret)
638b2e17252SHoward Wang 		return ret;
639b2e17252SHoward Wang 	else
640b2e17252SHoward Wang 		return 0;
641b2e17252SHoward Wang }
642b2e17252SHoward Wang 
643b2e17252SHoward Wang static int
6449b170cfcSHoward Wang rtl_dev_init(struct rte_eth_dev *dev)
6459b170cfcSHoward Wang {
6467d502791SHoward Wang 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
647f7327670SHoward Wang 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
6488e852260SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
6498e852260SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
6507d502791SHoward Wang 	struct rte_ether_addr *perm_addr = (struct rte_ether_addr *)hw->mac_addr;
6517d502791SHoward Wang 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
6528e852260SHoward Wang 
6539b170cfcSHoward Wang 	dev->dev_ops = &rtl_eth_dev_ops;
6541bbe869eSHoward Wang 	dev->tx_pkt_burst = &rtl_xmit_pkts;
6551bbe869eSHoward Wang 	dev->rx_pkt_burst = &rtl_recv_pkts;
6569b170cfcSHoward Wang 
6579b170cfcSHoward Wang 	/* For secondary processes, the primary process has done all the work */
6582f198f0aSHoward Wang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
6592f198f0aSHoward Wang 		if (dev->data->scattered_rx)
6602f198f0aSHoward Wang 			dev->rx_pkt_burst = &rtl_recv_scattered_pkts;
6619b170cfcSHoward Wang 		return 0;
6622f198f0aSHoward Wang 	}
6639b170cfcSHoward Wang 
6647d502791SHoward Wang 	hw->mmio_addr = (u8 *)pci_dev->mem_resource[2].addr; /* RTL8169 uses BAR2 */
6657d502791SHoward Wang 
6667d502791SHoward Wang 	rtl_get_mac_version(hw, pci_dev);
6677d502791SHoward Wang 
6688e852260SHoward Wang 	if (rtl_set_hw_ops(hw))
6698e852260SHoward Wang 		return -ENOTSUP;
6708e852260SHoward Wang 
671f7327670SHoward Wang 	rtl_disable_intr(hw);
672f7327670SHoward Wang 
6737d502791SHoward Wang 	rtl_hw_initialize(hw);
6747d502791SHoward Wang 
6757d502791SHoward Wang 	/* Read the permanent MAC address out of ROM */
6767d502791SHoward Wang 	rtl_get_mac_address(hw, perm_addr);
6777d502791SHoward Wang 
6787d502791SHoward Wang 	if (!rte_is_valid_assigned_ether_addr(perm_addr)) {
6797d502791SHoward Wang 		rte_eth_random_addr(&perm_addr->addr_bytes[0]);
6807d502791SHoward Wang 
6817d502791SHoward Wang 		rte_ether_format_addr(buf, sizeof(buf), perm_addr);
6827d502791SHoward Wang 
6837d502791SHoward Wang 		PMD_INIT_LOG(NOTICE, "r8169: Assign randomly generated MAC address %s", buf);
6847d502791SHoward Wang 	}
6857d502791SHoward Wang 
6867d502791SHoward Wang 	/* Allocate memory for storing MAC addresses */
6877d502791SHoward Wang 	dev->data->mac_addrs = rte_zmalloc("r8169", RTE_ETHER_ADDR_LEN, 0);
6887d502791SHoward Wang 
6897d502791SHoward Wang 	if (dev->data->mac_addrs == NULL) {
6907d502791SHoward Wang 		PMD_INIT_LOG(ERR, "MAC Malloc failed");
6917d502791SHoward Wang 		return -ENOMEM;
6927d502791SHoward Wang 	}
6937d502791SHoward Wang 
6947d502791SHoward Wang 	/* Copy the permanent MAC address */
6957d502791SHoward Wang 	rte_ether_addr_copy(perm_addr, &dev->data->mac_addrs[0]);
6967d502791SHoward Wang 
6977d502791SHoward Wang 	rtl_rar_set(hw, &perm_addr->addr_bytes[0]);
6987d502791SHoward Wang 
699f7327670SHoward Wang 	rte_intr_callback_register(intr_handle, rtl_dev_interrupt_handler, dev);
700f7327670SHoward Wang 
701f7327670SHoward Wang 	/* Enable uio/vfio intr/eventfd mapping */
702f7327670SHoward Wang 	rte_intr_enable(intr_handle);
703f7327670SHoward Wang 
7049b170cfcSHoward Wang 	return 0;
7059b170cfcSHoward Wang }
7069b170cfcSHoward Wang 
7079b170cfcSHoward Wang static int
7089b170cfcSHoward Wang rtl_dev_uninit(struct rte_eth_dev *dev)
7099b170cfcSHoward Wang {
7109b170cfcSHoward Wang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
7119b170cfcSHoward Wang 		return -EPERM;
7129b170cfcSHoward Wang 
7139b170cfcSHoward Wang 	rtl_dev_close(dev);
7149b170cfcSHoward Wang 
7159b170cfcSHoward Wang 	return 0;
7169b170cfcSHoward Wang }
7179b170cfcSHoward Wang 
7189b170cfcSHoward Wang static int
7199b170cfcSHoward Wang rtl_dev_reset(struct rte_eth_dev *dev)
7209b170cfcSHoward Wang {
7219b170cfcSHoward Wang 	int ret;
7229b170cfcSHoward Wang 
7239b170cfcSHoward Wang 	ret = rtl_dev_uninit(dev);
7249b170cfcSHoward Wang 	if (ret)
7259b170cfcSHoward Wang 		return ret;
7269b170cfcSHoward Wang 
7279b170cfcSHoward Wang 	ret = rtl_dev_init(dev);
7289b170cfcSHoward Wang 
7299b170cfcSHoward Wang 	return ret;
7309b170cfcSHoward Wang }
7319b170cfcSHoward Wang 
7329b170cfcSHoward Wang static int
7339b170cfcSHoward Wang rtl_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
7349b170cfcSHoward Wang 	      struct rte_pci_device *pci_dev)
7359b170cfcSHoward Wang {
7369b170cfcSHoward Wang 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct rtl_adapter),
7379b170cfcSHoward Wang 					     rtl_dev_init);
7389b170cfcSHoward Wang }
7399b170cfcSHoward Wang 
7409b170cfcSHoward Wang static int
7419b170cfcSHoward Wang rtl_pci_remove(struct rte_pci_device *pci_dev)
7429b170cfcSHoward Wang {
7439b170cfcSHoward Wang 	return rte_eth_dev_pci_generic_remove(pci_dev, rtl_dev_uninit);
7449b170cfcSHoward Wang }
7459b170cfcSHoward Wang 
7469b170cfcSHoward Wang static struct rte_pci_driver rte_r8169_pmd = {
7479b170cfcSHoward Wang 	.id_table  = pci_id_r8169_map,
7489b170cfcSHoward Wang 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
7499b170cfcSHoward Wang 	.probe     = rtl_pci_probe,
7509b170cfcSHoward Wang 	.remove    = rtl_pci_remove,
7519b170cfcSHoward Wang };
7529b170cfcSHoward Wang 
7539b170cfcSHoward Wang RTE_PMD_REGISTER_PCI(net_r8169, rte_r8169_pmd);
7549b170cfcSHoward Wang RTE_PMD_REGISTER_PCI_TABLE(net_r8169, pci_id_r8169_map);
7559b170cfcSHoward Wang RTE_PMD_REGISTER_KMOD_DEP(net_r8169, "* igb_uio | uio_pci_generic | vfio-pci");
756491aa390SHoward Wang 
757491aa390SHoward Wang RTE_LOG_REGISTER_SUFFIX(r8169_logtype_init, init, NOTICE)
758491aa390SHoward Wang RTE_LOG_REGISTER_SUFFIX(r8169_logtype_driver, driver, NOTICE)
759491aa390SHoward Wang #ifdef RTE_ETHDEV_DEBUG_RX
760491aa390SHoward Wang RTE_LOG_REGISTER_SUFFIX(r8169_logtype_rx, rx, DEBUG)
761491aa390SHoward Wang #endif
762491aa390SHoward Wang #ifdef RTE_ETHDEV_DEBUG_TX
763491aa390SHoward Wang RTE_LOG_REGISTER_SUFFIX(r8169_logtype_tx, tx, DEBUG)
764491aa390SHoward Wang #endif
765