Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  r8169_main.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * r8169.c: RealTek 8169/8168/8101 ethernet driver.
 *
 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
 * Copyright (c) a lot of people too. Please respect their work.
 *
 * See MAINTAINERS file for support contact information.
 */


#include <linux/module.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/if_vlan.h>
#include <linux/in.h>
#include <linux/io.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/bitfield.h>
#include <linux/prefetch.h>
#include <linux/ipv6.h>
#include <linux/unaligned.h>
#include <net/ip6_checksum.h>
#include <net/netdev_queues.h>

#include "r8169.h"
#include "r8169_firmware.h"

#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
#define FIRMWARE_8402_1  "rtl_nic/rtl8402-1.fw"
#define FIRMWARE_8411_1  "rtl_nic/rtl8411-1.fw"
#define FIRMWARE_8411_2  "rtl_nic/rtl8411-2.fw"
#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
#define FIRMWARE_8106E_2 "rtl_nic/rtl8106e-2.fw"
#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw"
#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw"
#define FIRMWARE_8168H_2 "rtl_nic/rtl8168h-2.fw"
#define FIRMWARE_8168FP_3 "rtl_nic/rtl8168fp-3.fw"
#define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw"
#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw"
#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw"
#define FIRMWARE_8125D_1 "rtl_nic/rtl8125d-1.fw"
#define FIRMWARE_8125D_2 "rtl_nic/rtl8125d-2.fw"
#define FIRMWARE_8125BP_2 "rtl_nic/rtl8125bp-2.fw"
#define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw"
#define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw"
#define FIRMWARE_8127A_1 "rtl_nic/rtl8127a-1.fw"

#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */

#define R8169_REGS_SIZE  256
#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)

#define OCP_STD_PHY_BASE 0xa400

#define RTL_CFG_NO_GBIT 1

/* write/read MMIO register */
#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg))
#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg))
#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg))
#define RTL_R8(tp, reg)  readb(tp->mmio_addr + (reg))
#define RTL_R16(tp, reg)  readw(tp->mmio_addr + (reg))
#define RTL_R32(tp, reg)  readl(tp->mmio_addr + (reg))

#define JUMBO_4K (4 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
#define JUMBO_6K (6 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
#define JUMBO_7K (7 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
#define JUMBO_9K (9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
#define JUMBO_16K (SZ_16K - VLAN_ETH_HLEN - ETH_FCS_LEN)

static const struct rtl_chip_info {
 u16 mask;
 u16 val;
 enum mac_version mac_version;
 const char *name;
 const char *fw_name;
} rtl_chip_infos[] = {
 /* 8127A family. */
 { 0x7cf, 0x6c9, RTL_GIGA_MAC_VER_80, "RTL8127A", FIRMWARE_8127A_1 },

 /* 8126A family. */
 { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_3 },
 { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_2 },

 /* 8125BP family. */
 { 0x7cf, 0x681, RTL_GIGA_MAC_VER_66, "RTL8125BP", FIRMWARE_8125BP_2 },

 /* 8125D family. */
 { 0x7cf, 0x689, RTL_GIGA_MAC_VER_64, "RTL8125D", FIRMWARE_8125D_2 },
 { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64, "RTL8125D", FIRMWARE_8125D_1 },

 /* 8125B family. */
 { 0x7cf, 0x641, RTL_GIGA_MAC_VER_63, "RTL8125B", FIRMWARE_8125B_2 },

 /* 8125A family. */
 { 0x7cf, 0x609, RTL_GIGA_MAC_VER_61, "RTL8125A", FIRMWARE_8125A_3 },

 /* RTL8117 */
 { 0x7cf, 0x54b, RTL_GIGA_MAC_VER_52, "RTL8168fp/RTL8117" },
 { 0x7cf, 0x54a, RTL_GIGA_MAC_VER_52, "RTL8168fp/RTL8117",
   FIRMWARE_8168FP_3 },

 /* 8168EP family. */
 { 0x7cf, 0x502, RTL_GIGA_MAC_VER_51, "RTL8168ep/8111ep" },

 /* 8168H family. */
 { 0x7cf, 0x541, RTL_GIGA_MAC_VER_46, "RTL8168h/8111h",
   FIRMWARE_8168H_2 },
 /* Realtek calls it RTL8168M, but it's handled like RTL8168H */
 { 0x7cf, 0x6c0, RTL_GIGA_MAC_VER_46, "RTL8168M", FIRMWARE_8168H_2 },

 /* 8168G family. */
 { 0x7cf, 0x5c8, RTL_GIGA_MAC_VER_44, "RTL8411b", FIRMWARE_8411_2 },
 { 0x7cf, 0x509, RTL_GIGA_MAC_VER_42, "RTL8168gu/8111gu",
   FIRMWARE_8168G_3 },
 { 0x7cf, 0x4c0, RTL_GIGA_MAC_VER_40, "RTL8168g/8111g",
   FIRMWARE_8168G_2 },

 /* 8168F family. */
 { 0x7c8, 0x488, RTL_GIGA_MAC_VER_38, "RTL8411", FIRMWARE_8411_1 },
 { 0x7cf, 0x481, RTL_GIGA_MAC_VER_36, "RTL8168f/8111f",
   FIRMWARE_8168F_2 },
 { 0x7cf, 0x480, RTL_GIGA_MAC_VER_35, "RTL8168f/8111f",
   FIRMWARE_8168F_1 },

 /* 8168E family. */
 { 0x7c8, 0x2c8, RTL_GIGA_MAC_VER_34, "RTL8168evl/8111evl",
   FIRMWARE_8168E_3 },
 { 0x7cf, 0x2c1, RTL_GIGA_MAC_VER_32, "RTL8168e/8111e",
   FIRMWARE_8168E_1 },
 { 0x7c8, 0x2c0, RTL_GIGA_MAC_VER_33, "RTL8168e/8111e",
   FIRMWARE_8168E_2 },

 /* 8168D family. */
 { 0x7cf, 0x281, RTL_GIGA_MAC_VER_25, "RTL8168d/8111d",
   FIRMWARE_8168D_1 },
 { 0x7c8, 0x280, RTL_GIGA_MAC_VER_26, "RTL8168d/8111d",
   FIRMWARE_8168D_2 },

 /* 8168DP family. */
 { 0x7cf, 0x28a, RTL_GIGA_MAC_VER_28, "RTL8168dp/8111dp" },
 { 0x7cf, 0x28b, RTL_GIGA_MAC_VER_31, "RTL8168dp/8111dp" },

 /* 8168C family. */
 { 0x7cf, 0x3c9, RTL_GIGA_MAC_VER_23, "RTL8168cp/8111cp" },
 { 0x7cf, 0x3c8, RTL_GIGA_MAC_VER_18, "RTL8168cp/8111cp" },
 { 0x7c8, 0x3c8, RTL_GIGA_MAC_VER_24, "RTL8168cp/8111cp" },
 { 0x7cf, 0x3c0, RTL_GIGA_MAC_VER_19, "RTL8168c/8111c" },
 { 0x7cf, 0x3c2, RTL_GIGA_MAC_VER_20, "RTL8168c/8111c" },
 { 0x7cf, 0x3c3, RTL_GIGA_MAC_VER_21, "RTL8168c/8111c" },
 { 0x7c8, 0x3c0, RTL_GIGA_MAC_VER_22, "RTL8168c/8111c" },

 /* 8168B family. */
 { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17, "RTL8168b/8111b" },
 /* This one is very old and rare, support has been removed.
 * { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11, "RTL8168b/8111b" },
 */


 /* 8101 family. */
 { 0x7c8, 0x448, RTL_GIGA_MAC_VER_39, "RTL8106e", FIRMWARE_8106E_1 },
 { 0x7c8, 0x440, RTL_GIGA_MAC_VER_37, "RTL8402", FIRMWARE_8402_1 },
 { 0x7cf, 0x409, RTL_GIGA_MAC_VER_29, "RTL8105e", FIRMWARE_8105E_1 },
 { 0x7c8, 0x408, RTL_GIGA_MAC_VER_30, "RTL8105e", FIRMWARE_8105E_1 },
 { 0x7cf, 0x349, RTL_GIGA_MAC_VER_08, "RTL8102e" },
 { 0x7cf, 0x249, RTL_GIGA_MAC_VER_08, "RTL8102e" },
 { 0x7cf, 0x348, RTL_GIGA_MAC_VER_07, "RTL8102e" },
 { 0x7cf, 0x248, RTL_GIGA_MAC_VER_07, "RTL8102e" },
 { 0x7cf, 0x240, RTL_GIGA_MAC_VER_14, "RTL8401" },
 { 0x7c8, 0x348, RTL_GIGA_MAC_VER_09, "RTL8102e/RTL8103e" },
 { 0x7c8, 0x248, RTL_GIGA_MAC_VER_09, "RTL8102e/RTL8103e" },
 { 0x7c8, 0x340, RTL_GIGA_MAC_VER_10, "RTL8101e/RTL8100e" },

 /* 8110 family. */
 { 0xfc8, 0x980, RTL_GIGA_MAC_VER_06, "RTL8169sc/8110sc" },
 { 0xfc8, 0x180, RTL_GIGA_MAC_VER_05, "RTL8169sc/8110sc" },
 { 0xfc8, 0x100, RTL_GIGA_MAC_VER_04, "RTL8169sb/8110sb" },
 { 0xfc8, 0x040, RTL_GIGA_MAC_VER_03, "RTL8110s" },
 { 0xfc8, 0x008, RTL_GIGA_MAC_VER_02, "RTL8169s" },

 /* Catch-all */
 { 0x000, 0x000, RTL_GIGA_MAC_NONE }
};

static const struct pci_device_id rtl8169_pci_tbl[] = {
 { PCI_VDEVICE(REALTEK, 0x2502) },
 { PCI_VDEVICE(REALTEK, 0x2600) },
 { PCI_VDEVICE(REALTEK, 0x8129) },
 { PCI_VDEVICE(REALTEK, 0x8136), RTL_CFG_NO_GBIT },
 { PCI_VDEVICE(REALTEK, 0x8161) },
 { PCI_VDEVICE(REALTEK, 0x8162) },
 { PCI_VDEVICE(REALTEK, 0x8167) },
 { PCI_VDEVICE(REALTEK, 0x8168) },
 { PCI_VDEVICE(NCUBE, 0x8168) },
 { PCI_VDEVICE(REALTEK, 0x8169) },
 { PCI_VDEVICE(DLINK, 0x4300) },
 { PCI_VDEVICE(DLINK, 0x4302) },
 { PCI_VDEVICE(AT, 0xc107) },
 { PCI_VDEVICE(USR, 0x0116) },
 { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 },
 { 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
 { PCI_VDEVICE(REALTEK, 0x8125) },
 { PCI_VDEVICE(REALTEK, 0x8126) },
 { PCI_VDEVICE(REALTEK, 0x8127) },
 { PCI_VDEVICE(REALTEK, 0x3000) },
 { PCI_VDEVICE(REALTEK, 0x5000) },
 { PCI_VDEVICE(REALTEK, 0x0e10) },
 {}
};

MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);

enum rtl_registers {
 MAC0  = 0, /* Ethernet hardware address. */
 MAC4  = 4,
 MAR0  = 8, /* Multicast filter. */
 CounterAddrLow  = 0x10,
 CounterAddrHigh  = 0x14,
 TxDescStartAddrLow = 0x20,
 TxDescStartAddrHigh = 0x24,
 TxHDescStartAddrLow = 0x28,
 TxHDescStartAddrHigh = 0x2c,
 FLASH  = 0x30,
 ERSR  = 0x36,
 ChipCmd  = 0x37,
 TxPoll  = 0x38,
 IntrMask = 0x3c,
 IntrStatus = 0x3e,

 TxConfig = 0x40,
#define TXCFG_AUTO_FIFO   (1 << 7) /* 8111e-vl */
#define TXCFG_EMPTY   (1 << 11) /* 8111e-vl */

 RxConfig = 0x44,
#define RX128_INT_EN   (1 << 15) /* 8111c and later */
#define RX_MULTI_EN   (1 << 14) /* 8111c only */
#define RXCFG_FIFO_SHIFT  13
     /* No threshold before first PCI xfer */
#define RX_FIFO_THRESH   (7 << RXCFG_FIFO_SHIFT)
#define RX_EARLY_OFF   (1 << 11)
#define RX_PAUSE_SLOT_ON  (1 << 11) /* 8125b and later */
#define RXCFG_DMA_SHIFT   8
     /* Unlimited maximum PCI burst. */
#define RX_DMA_BURST   (7 << RXCFG_DMA_SHIFT)

 Cfg9346  = 0x50,
 Config0  = 0x51,
 Config1  = 0x52,
 Config2  = 0x53,
#define PME_SIGNAL   (1 << 5) /* 8168c and later */

 Config3  = 0x54,
 Config4  = 0x55,
 Config5  = 0x56,
 PHYAR  = 0x60,
 PHYstatus = 0x6c,
 RxMaxSize = 0xda,
 CPlusCmd = 0xe0,
 IntrMitigate = 0xe2,

#define RTL_COALESCE_TX_USECS GENMASK(15, 12)
#define RTL_COALESCE_TX_FRAMES GENMASK(11, 8)
#define RTL_COALESCE_RX_USECS GENMASK(7, 4)
#define RTL_COALESCE_RX_FRAMES GENMASK(3, 0)

#define RTL_COALESCE_T_MAX 0x0fU
#define RTL_COALESCE_FRAME_MAX (RTL_COALESCE_T_MAX * 4)

 RxDescAddrLow = 0xe4,
 RxDescAddrHigh = 0xe8,
 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */

#define NoEarlyTx 0x3f /* Max value : no early transmit. */

 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */

#define TxPacketMax (8064 >> 7)
#define EarlySize 0x27

 FuncEvent = 0xf0,
 FuncEventMask = 0xf4,
 FuncPresetState = 0xf8,
 IBCR0           = 0xf8,
 IBCR2           = 0xf9,
 IBIMR0          = 0xfa,
 IBISR0          = 0xfb,
 FuncForceEvent = 0xfc,
};

enum rtl8168_8101_registers {
 CSIDR   = 0x64,
 CSIAR   = 0x68,
#define CSIAR_FLAG   0x80000000
#define CSIAR_WRITE_CMD   0x80000000
#define CSIAR_BYTE_ENABLE  0x0000f000
#define CSIAR_ADDR_MASK   0x00000fff
 PMCH   = 0x6f,
#define D3COLD_NO_PLL_DOWN  BIT(7)
#define D3HOT_NO_PLL_DOWN  BIT(6)
#define D3_NO_PLL_DOWN   (BIT(7) | BIT(6))
 EPHYAR   = 0x80,
#define EPHYAR_FLAG   0x80000000
#define EPHYAR_WRITE_CMD  0x80000000
#define EPHYAR_REG_MASK   0x1f
#define EPHYAR_REG_SHIFT  16
#define EPHYAR_DATA_MASK  0xffff
 DLLPR   = 0xd0,
#define PFM_EN    (1 << 6)
#define TX_10M_PS_EN   (1 << 7)
 DBG_REG   = 0xd1,
#define FIX_NAK_1   (1 << 4)
#define FIX_NAK_2   (1 << 3)
 TWSI   = 0xd2,
 MCU   = 0xd3,
#define NOW_IS_OOB   (1 << 7)
#define TX_EMPTY   (1 << 5)
#define RX_EMPTY   (1 << 4)
#define RXTX_EMPTY   (TX_EMPTY | RX_EMPTY)
#define EN_NDP    (1 << 3)
#define EN_OOB_RESET   (1 << 2)
#define LINK_LIST_RDY   (1 << 1)
 EFUSEAR   = 0xdc,
#define EFUSEAR_FLAG   0x80000000
#define EFUSEAR_WRITE_CMD  0x80000000
#define EFUSEAR_READ_CMD  0x00000000
#define EFUSEAR_REG_MASK  0x03ff
#define EFUSEAR_REG_SHIFT  8
#define EFUSEAR_DATA_MASK  0xff
 MISC_1   = 0xf2,
#define PFM_D3COLD_EN   (1 << 6)
};

enum rtl8168_registers {
 LED_CTRL  = 0x18,
 LED_FREQ  = 0x1a,
 EEE_LED   = 0x1b,
 ERIDR   = 0x70,
 ERIAR   = 0x74,
#define ERIAR_FLAG   0x80000000
#define ERIAR_WRITE_CMD   0x80000000
#define ERIAR_READ_CMD   0x00000000
#define ERIAR_ADDR_BYTE_ALIGN  4
#define ERIAR_TYPE_SHIFT  16
#define ERIAR_EXGMAC   (0x00 << ERIAR_TYPE_SHIFT)
#define ERIAR_MSIX   (0x01 << ERIAR_TYPE_SHIFT)
#define ERIAR_ASF   (0x02 << ERIAR_TYPE_SHIFT)
#define ERIAR_OOB   (0x02 << ERIAR_TYPE_SHIFT)
#define ERIAR_MASK_SHIFT  12
#define ERIAR_MASK_0001   (0x1 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0011   (0x3 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0100   (0x4 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0101   (0x5 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_1111   (0xf << ERIAR_MASK_SHIFT)
 EPHY_RXER_NUM  = 0x7c,
 OCPDR   = 0xb0, /* OCP GPHY access */
#define OCPDR_WRITE_CMD   0x80000000
#define OCPDR_READ_CMD   0x00000000
#define OCPDR_REG_MASK   0x7f
#define OCPDR_GPHY_REG_SHIFT  16
#define OCPDR_DATA_MASK   0xffff
 OCPAR   = 0xb4,
#define OCPAR_FLAG   0x80000000
#define OCPAR_GPHY_WRITE_CMD  0x8000f060
#define OCPAR_GPHY_READ_CMD  0x0000f060
 GPHY_OCP  = 0xb8,
 RDSAR1   = 0xd0, /* 8168c only. Undocumented on 8168dp */
 MISC   = 0xf0, /* 8168e only. */
#define TXPLA_RST   (1 << 29)
#define DISABLE_LAN_EN   (1 << 23) /* Enable GPIO pin */
#define PWM_EN    (1 << 22)
#define RXDV_GATED_EN   (1 << 19)
#define EARLY_TALLY_EN   (1 << 16)
};

enum rtl8125_registers {
 LEDSEL0   = 0x18,
 INT_CFG0_8125  = 0x34,
#define INT_CFG0_ENABLE_8125  BIT(0)
#define INT_CFG0_CLKREQEN  BIT(3)
 IntrMask_8125  = 0x38,
 IntrStatus_8125  = 0x3c,
 INT_CFG1_8125  = 0x7a,
 LEDSEL2   = 0x84,
 LEDSEL1   = 0x86,
 TxPoll_8125  = 0x90,
 LEDSEL3   = 0x96,
 MAC0_BKP  = 0x19e0,
 RSS_CTRL_8125  = 0x4500,
 Q_NUM_CTRL_8125  = 0x4800,
 EEE_TXIDLE_TIMER_8125 = 0x6048,
};

#define LEDSEL_MASK_8125 0x23f

#define RX_VLAN_INNER_8125 BIT(22)
#define RX_VLAN_OUTER_8125 BIT(23)
#define RX_VLAN_8125  (RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125)

#define RX_FETCH_DFLT_8125 (8 << 27)

enum rtl_register_content {
 /* InterruptStatusBits */
 SYSErr  = 0x8000,
 PCSTimeout = 0x4000,
 SWInt  = 0x0100,
 TxDescUnavail = 0x0080,
 RxFIFOOver = 0x0040,
 LinkChg  = 0x0020,
 RxOverflow = 0x0010,
 TxErr  = 0x0008,
 TxOK  = 0x0004,
 RxErr  = 0x0002,
 RxOK  = 0x0001,

 /* RxStatusDesc */
 RxRWT = (1 << 22),
 RxRES = (1 << 21),
 RxRUNT = (1 << 20),
 RxCRC = (1 << 19),

 /* ChipCmdBits */
 StopReq  = 0x80,
 CmdReset = 0x10,
 CmdRxEnb = 0x08,
 CmdTxEnb = 0x04,
 RxBufEmpty = 0x01,

 /* TXPoll register p.5 */
 HPQ  = 0x80,  /* Poll cmd on the high prio queue */
 NPQ  = 0x40,  /* Poll cmd on the low prio queue */
 FSWInt  = 0x01,  /* Forced software interrupt */

 /* Cfg9346Bits */
 Cfg9346_Lock = 0x00,
 Cfg9346_Unlock = 0xc0,

 /* rx_mode_bits */
 AcceptErr = 0x20,
 AcceptRunt = 0x10,
#define RX_CONFIG_ACCEPT_ERR_MASK 0x30
 AcceptBroadcast = 0x08,
 AcceptMulticast = 0x04,
 AcceptMyPhys = 0x02,
 AcceptAllPhys = 0x01,
#define RX_CONFIG_ACCEPT_OK_MASK 0x0f
#define RX_CONFIG_ACCEPT_MASK  0x3f

 /* TxConfigBits */
 TxInterFrameGapShift = 24,
 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */

 /* Config1 register p.24 */
 LEDS1  = (1 << 7),
 LEDS0  = (1 << 6),
 Speed_down = (1 << 4),
 MEMMAP  = (1 << 3),
 IOMAP  = (1 << 2),
 VPD  = (1 << 1),
 PMEnable = (1 << 0), /* Power Management Enable */

 /* Config2 register p. 25 */
 ClkReqEn = (1 << 7), /* Clock Request Enable */
 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
 PCI_Clock_66MHz = 0x01,
 PCI_Clock_33MHz = 0x00,

 /* Config3 register p.25 */
 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
 LinkUp  = (1 << 4), /* Wake up when the cable connection is re-established */
 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
 Rdy_to_L23 = (1 << 1), /* L23 Enable */
 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */

 /* Config4 register */
 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */

 /* Config5 register p.27 */
 BWF  = (1 << 6), /* Accept Broadcast wakeup frame */
 MWF  = (1 << 5), /* Accept Multicast wakeup frame */
 UWF  = (1 << 4), /* Accept Unicast wakeup frame */
 Spi_en  = (1 << 3),
 LanWake  = (1 << 1), /* LanWake enable/disable */
 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
 ASPM_en  = (1 << 0), /* ASPM enable */

 /* CPlusCmd p.31 */
 EnableBist = (1 << 15), // 8168 8101
 Mac_dbgo_oe = (1 << 14), // 8168 8101
 EnAnaPLL = (1 << 14), // 8169
 Normal_mode = (1 << 13), // unused
 Force_half_dup = (1 << 12), // 8168 8101
 Force_rxflow_en = (1 << 11), // 8168 8101
 Force_txflow_en = (1 << 10), // 8168 8101
 Cxpl_dbg_sel = (1 << 9), // 8168 8101
 ASF  = (1 << 8), // 8168 8101
 PktCntrDisable = (1 << 7), // 8168 8101
 Mac_dbgo_sel = 0x001c, // 8168
 RxVlan  = (1 << 6),
 RxChkSum = (1 << 5),
 PCIDAC  = (1 << 4),
 PCIMulRW = (1 << 3),
#define INTT_MASK GENMASK(1, 0)
#define CPCMD_MASK (Normal_mode | RxVlan | RxChkSum | INTT_MASK)

 /* rtl8169_PHYstatus */
 TBI_Enable = 0x80,
 TxFlowCtrl = 0x40,
 RxFlowCtrl = 0x20,
 _1000bpsF = 0x10,
 _100bps  = 0x08,
 _10bps  = 0x04,
 LinkStatus = 0x02,
 FullDup  = 0x01,

 /* ResetCounterCommand */
 CounterReset = 0x1,

 /* DumpCounterCommand */
 CounterDump = 0x8,

 /* magic enable v2 */
 MagicPacket_v2 = (1 << 16), /* Wake up when receives a Magic Packet */
};

enum rtl_desc_bit {
 /* First doubleword. */
 DescOwn  = (1 << 31), /* Descriptor is owned by NIC */
 RingEnd  = (1 << 30), /* End of descriptor ring */
 FirstFrag = (1 << 29), /* First segment of a packet */
 LastFrag = (1 << 28), /* Final segment of a packet */
};

/* Generic case. */
enum rtl_tx_desc_bit {
 /* First doubleword. */
 TD_LSO  = (1 << 27),  /* Large Send Offload */
#define TD_MSS_MAX   0x07ffu /* MSS value */

 /* Second doubleword. */
 TxVlanTag = (1 << 17),  /* Add VLAN tag */
};

/* 8169, 8168b and 810x except 8102e. */
enum rtl_tx_desc_bit_0 {
 /* First doubleword. */
#define TD0_MSS_SHIFT   16 /* MSS position (11 bits) */
 TD0_TCP_CS = (1 << 16),  /* Calculate TCP/IP checksum */
 TD0_UDP_CS = (1 << 17),  /* Calculate UDP/IP checksum */
 TD0_IP_CS = (1 << 18),  /* Calculate IP checksum */
};

/* 8102e, 8168c and beyond. */
enum rtl_tx_desc_bit_1 {
 /* First doubleword. */
 TD1_GTSENV4 = (1 << 26),  /* Giant Send for IPv4 */
 TD1_GTSENV6 = (1 << 25),  /* Giant Send for IPv6 */
#define GTTCPHO_SHIFT   18
#define GTTCPHO_MAX   0x7f

 /* Second doubleword. */
#define TCPHO_SHIFT   18
#define TCPHO_MAX   0x3ff
#define TD1_MSS_SHIFT   18 /* MSS position (11 bits) */
 TD1_IPv6_CS = (1 << 28),  /* Calculate IPv6 checksum */
 TD1_IPv4_CS = (1 << 29),  /* Calculate IPv4 checksum */
 TD1_TCP_CS = (1 << 30),  /* Calculate TCP/IP checksum */
 TD1_UDP_CS = (1 << 31),  /* Calculate UDP/IP checksum */
};

enum rtl_rx_desc_bit {
 /* Rx private */
 PID1  = (1 << 18), /* Protocol ID bit 1/2 */
 PID0  = (1 << 17), /* Protocol ID bit 0/2 */

#define RxProtoUDP (PID1)
#define RxProtoTCP (PID0)
#define RxProtoIP (PID1 | PID0)
#define RxProtoMask RxProtoIP

 IPFail  = (1 << 16), /* IP checksum failed */
 UDPFail  = (1 << 15), /* UDP/IP checksum failed */
 TCPFail  = (1 << 14), /* TCP/IP checksum failed */

#define RxCSFailMask (IPFail | UDPFail | TCPFail)

 RxVlanTag = (1 << 16), /* VLAN tag available */
};

#define RTL_GSO_MAX_SIZE_V1 32000
#define RTL_GSO_MAX_SEGS_V1 24
#define RTL_GSO_MAX_SIZE_V2 64000
#define RTL_GSO_MAX_SEGS_V2 64

struct TxDesc {
 __le32 opts1;
 __le32 opts2;
 __le64 addr;
};

struct RxDesc {
 __le32 opts1;
 __le32 opts2;
 __le64 addr;
};

struct ring_info {
 struct sk_buff *skb;
 u32  len;
};

struct rtl8169_counters {
 __le64 tx_packets;
 __le64 rx_packets;
 __le64 tx_errors;
 __le32 rx_errors;
 __le16 rx_missed;
 __le16 align_errors;
 __le32 tx_one_collision;
 __le32 tx_multi_collision;
 __le64 rx_unicast;
 __le64 rx_broadcast;
 __le32 rx_multicast;
 __le16 tx_aborted;
 __le16 tx_underrun;
 /* new since RTL8125 */
 __le64 tx_octets;
 __le64 rx_octets;
 __le64 rx_multicast64;
 __le64 tx_unicast64;
 __le64 tx_broadcast64;
 __le64 tx_multicast64;
 __le32 tx_pause_on;
 __le32 tx_pause_off;
 __le32 tx_pause_all;
 __le32 tx_deferred;
 __le32 tx_late_collision;
 __le32 tx_all_collision;
 __le32 tx_aborted32;
 __le32 align_errors32;
 __le32 rx_frame_too_long;
 __le32 rx_runt;
 __le32 rx_pause_on;
 __le32 rx_pause_off;
 __le32 rx_pause_all;
 __le32 rx_unknown_opcode;
 __le32 rx_mac_error;
 __le32 tx_underrun32;
 __le32 rx_mac_missed;
 __le32 rx_tcam_dropped;
 __le32 tdu;
 __le32 rdu;
};

struct rtl8169_tc_offsets {
 bool inited;
 __le64 tx_errors;
 __le32 tx_multi_collision;
 __le16 tx_aborted;
 __le16 rx_missed;
};

enum rtl_flag {
 RTL_FLAG_TASK_RESET_PENDING,
 RTL_FLAG_TASK_TX_TIMEOUT,
 RTL_FLAG_MAX
};

enum rtl_dash_type {
 RTL_DASH_NONE,
 RTL_DASH_DP,
 RTL_DASH_EP,
 RTL_DASH_25_BP,
};

struct rtl8169_private {
 void __iomem *mmio_addr; /* memory map physical address */
 struct pci_dev *pci_dev;
 struct net_device *dev;
 struct phy_device *phydev;
 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. */
 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 */
 u16 cp_cmd;
 u16 tx_lpi_timer;
 u32 irq_mask;
 int irq;
 struct clk *clk;

 struct {
  DECLARE_BITMAP(flags, RTL_FLAG_MAX);
  struct work_struct work;
 } wk;

 raw_spinlock_t mac_ocp_lock;
 struct mutex led_lock; /* serialize LED ctrl RMW access */

 unsigned supports_gmii:1;
 unsigned aspm_manageable:1;
 unsigned dash_enabled:1;
 dma_addr_t counters_phys_addr;
 struct rtl8169_counters *counters;
 struct rtl8169_tc_offsets tc_offset;
 u32 saved_wolopts;

 const char *fw_name;
 struct rtl_fw *rtl_fw;

 struct r8169_led_classdev *leds;

 u32 ocp_base;
};

typedef void (*rtl_generic_fct)(struct rtl8169_private *tp);

MODULE_AUTHOR("Realtek and the Linux r8169 crew ");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
MODULE_SOFTDEP("pre: realtek");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_8168D_1);
MODULE_FIRMWARE(FIRMWARE_8168D_2);
MODULE_FIRMWARE(FIRMWARE_8168E_1);
MODULE_FIRMWARE(FIRMWARE_8168E_2);
MODULE_FIRMWARE(FIRMWARE_8168E_3);
MODULE_FIRMWARE(FIRMWARE_8105E_1);
MODULE_FIRMWARE(FIRMWARE_8168F_1);
MODULE_FIRMWARE(FIRMWARE_8168F_2);
MODULE_FIRMWARE(FIRMWARE_8402_1);
MODULE_FIRMWARE(FIRMWARE_8411_1);
MODULE_FIRMWARE(FIRMWARE_8411_2);
MODULE_FIRMWARE(FIRMWARE_8106E_1);
MODULE_FIRMWARE(FIRMWARE_8106E_2);
MODULE_FIRMWARE(FIRMWARE_8168G_2);
MODULE_FIRMWARE(FIRMWARE_8168G_3);
MODULE_FIRMWARE(FIRMWARE_8168H_2);
MODULE_FIRMWARE(FIRMWARE_8168FP_3);
MODULE_FIRMWARE(FIRMWARE_8107E_2);
MODULE_FIRMWARE(FIRMWARE_8125A_3);
MODULE_FIRMWARE(FIRMWARE_8125B_2);
MODULE_FIRMWARE(FIRMWARE_8125D_1);
MODULE_FIRMWARE(FIRMWARE_8125D_2);
MODULE_FIRMWARE(FIRMWARE_8125BP_2);
MODULE_FIRMWARE(FIRMWARE_8126A_2);
MODULE_FIRMWARE(FIRMWARE_8126A_3);
MODULE_FIRMWARE(FIRMWARE_8127A_1);

static inline struct device *tp_to_dev(struct rtl8169_private *tp)
{
 return &tp->pci_dev->dev;
}

static void rtl_lock_config_regs(struct rtl8169_private *tp)
{
 RTL_W8(tp, Cfg9346, Cfg9346_Lock);
}

static void rtl_unlock_config_regs(struct rtl8169_private *tp)
{
 RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
}

static void rtl_pci_commit(struct rtl8169_private *tp)
{
 /* Read an arbitrary register to commit a preceding PCI write */
 RTL_R8(tp, ChipCmd);
}

static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
{
 u8 val;

 val = RTL_R8(tp, Config2);
 RTL_W8(tp, Config2, (val & ~clear) | set);
}

static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
{
 u8 val;

 val = RTL_R8(tp, Config5);
 RTL_W8(tp, Config5, (val & ~clear) | set);
}

static void r8169_mod_reg8_cond(struct rtl8169_private *tp, int reg,
    u8 bits, bool cond)
{
 u8 val, old_val;

 old_val = RTL_R8(tp, reg);
 if (cond)
  val = old_val | bits;
 else
  val = old_val & ~bits;
 if (val != old_val)
  RTL_W8(tp, reg, val);
}

static bool rtl_is_8125(struct rtl8169_private *tp)
{
 return tp->mac_version >= RTL_GIGA_MAC_VER_61;
}

static bool rtl_is_8168evl_up(struct rtl8169_private *tp)
{
 return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
        tp->mac_version != RTL_GIGA_MAC_VER_39 &&
        tp->mac_version <= RTL_GIGA_MAC_VER_52;
}

static bool rtl_supports_eee(struct rtl8169_private *tp)
{
 return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
        tp->mac_version != RTL_GIGA_MAC_VER_37 &&
        tp->mac_version != RTL_GIGA_MAC_VER_39;
}

static void rtl_read_mac_from_reg(struct rtl8169_private *tp, u8 *mac, int reg)
{
 int i;

 for (i = 0; i < ETH_ALEN; i++)
  mac[i] = RTL_R8(tp, reg + i);
}

struct rtl_cond {
 bool (*check)(struct rtl8169_private *);
 const char *msg;
};

static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
     unsigned long usecs, int n, bool high)
{
 int i;

 for (i = 0; i < n; i++) {
  if (c->check(tp) == high)
   return true;
  fsleep(usecs);
 }

 if (net_ratelimit())
  netdev_err(tp->dev, "%s == %d (loop: %d, delay: %lu).\n",
      c->msg, !high, n, usecs);
 return false;
}

static bool rtl_loop_wait_high(struct rtl8169_private *tp,
          const struct rtl_cond *c,
          unsigned long d, int n)
{
 return rtl_loop_wait(tp, c, d, n, true);
}

static bool rtl_loop_wait_low(struct rtl8169_private *tp,
         const struct rtl_cond *c,
         unsigned long d, int n)
{
 return rtl_loop_wait(tp, c, d, n, false);
}

#define DECLARE_RTL_COND(name)    \
static bool name ## _check(struct rtl8169_private *); \
       \
static const struct rtl_cond name = {   \
 .check = name ## _check,   \
 .msg = #name     \
};       \
       \
static bool name ## _check(struct rtl8169_private *tp)

int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val)
{
 struct device *dev = tp_to_dev(tp);
 int ret;

 ret = pm_runtime_resume_and_get(dev);
 if (ret < 0)
  return ret;

 mutex_lock(&tp->led_lock);
 RTL_W16(tp, LED_CTRL, (RTL_R16(tp, LED_CTRL) & ~mask) | val);
 mutex_unlock(&tp->led_lock);

 pm_runtime_put_sync(dev);

 return 0;
}

int rtl8168_get_led_mode(struct rtl8169_private *tp)
{
 struct device *dev = tp_to_dev(tp);
 int ret;

 ret = pm_runtime_resume_and_get(dev);
 if (ret < 0)
  return ret;

 ret = RTL_R16(tp, LED_CTRL);

 pm_runtime_put_sync(dev);

 return ret;
}

static int rtl8125_get_led_reg(int index)
{
 static const int led_regs[] = { LEDSEL0, LEDSEL1, LEDSEL2, LEDSEL3 };

 return led_regs[index];
}

int rtl8125_set_led_mode(struct rtl8169_private *tp, int index, u16 mode)
{
 int reg = rtl8125_get_led_reg(index);
 struct device *dev = tp_to_dev(tp);
 int ret;
 u16 val;

 ret = pm_runtime_resume_and_get(dev);
 if (ret < 0)
  return ret;

 mutex_lock(&tp->led_lock);
 val = RTL_R16(tp, reg) & ~LEDSEL_MASK_8125;
 RTL_W16(tp, reg, val | mode);
 mutex_unlock(&tp->led_lock);

 pm_runtime_put_sync(dev);

 return 0;
}

int rtl8125_get_led_mode(struct rtl8169_private *tp, int index)
{
 int reg = rtl8125_get_led_reg(index);
 struct device *dev = tp_to_dev(tp);
 int ret;

 ret = pm_runtime_resume_and_get(dev);
 if (ret < 0)
  return ret;

 ret = RTL_R16(tp, reg);

 pm_runtime_put_sync(dev);

 return ret;
}

void r8169_get_led_name(struct rtl8169_private *tp, int idx,
   char *buf, int buf_len)
{
 struct pci_dev *pdev = tp->pci_dev;
 char pdom[8], pfun[8];
 int domain;

 domain = pci_domain_nr(pdev->bus);
 if (domain)
  snprintf(pdom, sizeof(pdom), "P%d", domain);
 else
  pdom[0] = '\0';

 if (pdev->multifunction)
  snprintf(pfun, sizeof(pfun), "f%d", PCI_FUNC(pdev->devfn));
 else
  pfun[0] = '\0';

 snprintf(buf, buf_len, "en%sp%ds%d%s-%d::lan", pdom, pdev->bus->number,
   PCI_SLOT(pdev->devfn), pfun, idx);
}

static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
{
 /* based on RTL8168FP_OOBMAC_BASE in vendor driver */
 if (type == ERIAR_OOB && tp->mac_version == RTL_GIGA_MAC_VER_52)
  *cmd |= 0xf70 << 18;
}

DECLARE_RTL_COND(rtl_eriar_cond)
{
 return RTL_R32(tp, ERIAR) & ERIAR_FLAG;
}

static void _rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
      u32 val, int type)
{
 u32 cmd = ERIAR_WRITE_CMD | type | mask | addr;

 if (WARN(addr & 3 || !mask, "addr: 0x%x, mask: 0x%08x\n", addr, mask))
  return;

 RTL_W32(tp, ERIDR, val);
 r8168fp_adjust_ocp_cmd(tp, &cmd, type);
 RTL_W32(tp, ERIAR, cmd);

 rtl_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
}

static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
     u32 val)
{
 _rtl_eri_write(tp, addr, mask, val, ERIAR_EXGMAC);
}

static u32 _rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
{
 u32 cmd = ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr;

 r8168fp_adjust_ocp_cmd(tp, &cmd, type);
 RTL_W32(tp, ERIAR, cmd);

 return rtl_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
  RTL_R32(tp, ERIDR) : ~0;
}

static u32 rtl_eri_read(struct rtl8169_private *tp, int addr)
{
 return _rtl_eri_read(tp, addr, ERIAR_EXGMAC);
}

static void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 p, u32 m)
{
 u32 val = rtl_eri_read(tp, addr);

 rtl_eri_write(tp, addr, ERIAR_MASK_1111, (val & ~m) | p);
}

static void rtl_eri_set_bits(struct rtl8169_private *tp, int addr, u32 p)
{
 rtl_w0w1_eri(tp, addr, p, 0);
}

static void rtl_eri_clear_bits(struct rtl8169_private *tp, int addr, u32 m)
{
 rtl_w0w1_eri(tp, addr, 0, m);
}

static bool rtl_ocp_reg_failure(u32 reg)
{
 return WARN_ONCE(reg & 0xffff0001, "Invalid ocp reg %x!\n", reg);
}

DECLARE_RTL_COND(rtl_ocp_gphy_cond)
{
 return RTL_R32(tp, GPHY_OCP) & OCPAR_FLAG;
}

static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
{
 if (rtl_ocp_reg_failure(reg))
  return;

 RTL_W32(tp, GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);

 rtl_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
}

static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
{
 if (rtl_ocp_reg_failure(reg))
  return 0;

 RTL_W32(tp, GPHY_OCP, reg << 15);

 return rtl_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
  (RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
}

static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
{
 if (rtl_ocp_reg_failure(reg))
  return;

 RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
}

static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
{
 unsigned long flags;

 raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
 __r8168_mac_ocp_write(tp, reg, data);
 raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
}

static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
{
 if (rtl_ocp_reg_failure(reg))
  return 0;

 RTL_W32(tp, OCPDR, reg << 15);

 return RTL_R32(tp, OCPDR);
}

static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
{
 unsigned long flags;
 u16 val;

 raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
 val = __r8168_mac_ocp_read(tp, reg);
 raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);

 return val;
}

static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
     u16 set)
{
 unsigned long flags;
 u16 data;

 raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
 data = __r8168_mac_ocp_read(tp, reg);
 __r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
 raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
}

/* Work around a hw issue with RTL8168g PHY, the quirk disables
 * PHY MCU interrupts before PHY power-down.
 */

static void rtl8168g_phy_suspend_quirk(struct rtl8169_private *tp, int value)
{
 switch (tp->mac_version) {
 case RTL_GIGA_MAC_VER_40:
  if (value & BMCR_RESET || !(value & BMCR_PDOWN))
   rtl_eri_set_bits(tp, 0x1a8, 0xfc000000);
  else
   rtl_eri_clear_bits(tp, 0x1a8, 0xfc000000);
  break;
 default:
  break;
 }
};

static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
{
 if (reg == 0x1f) {
  tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
  return;
 }

 if (tp->ocp_base != OCP_STD_PHY_BASE)
  reg -= 0x10;

 if (tp->ocp_base == OCP_STD_PHY_BASE && reg == MII_BMCR)
  rtl8168g_phy_suspend_quirk(tp, value);

 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
}

static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
{
 if (reg == 0x1f)
  return tp->ocp_base == OCP_STD_PHY_BASE ? 0 : tp->ocp_base >> 4;

 if (tp->ocp_base != OCP_STD_PHY_BASE)
  reg -= 0x10;

 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
}

static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
{
 if (reg == 0x1f) {
  tp->ocp_base = value << 4;
  return;
 }

 r8168_mac_ocp_write(tp, tp->ocp_base + reg, value);
}

static int mac_mcu_read(struct rtl8169_private *tp, int reg)
{
 return r8168_mac_ocp_read(tp, tp->ocp_base + reg);
}

DECLARE_RTL_COND(rtl_phyar_cond)
{
 return RTL_R32(tp, PHYAR) & 0x80000000;
}

static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
{
 RTL_W32(tp, PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));

 rtl_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
 /*
 * According to hardware specs a 20us delay is required after write
 * complete indication, but before sending next command.
 */

 udelay(20);
}

static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
{
 int value;

 RTL_W32(tp, PHYAR, 0x0 | (reg & 0x1f) << 16);

 value = rtl_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
  RTL_R32(tp, PHYAR) & 0xffff : -ETIMEDOUT;

 /*
 * According to hardware specs a 20us delay is required after read
 * complete indication, but before sending next command.
 */

 udelay(20);

 return value;
}

DECLARE_RTL_COND(rtl_ocpar_cond)
{
 return RTL_R32(tp, OCPAR) & OCPAR_FLAG;
}

#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000

static void r8168dp_2_mdio_start(struct rtl8169_private *tp)
{
 RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
}

static void r8168dp_2_mdio_stop(struct rtl8169_private *tp)
{
 RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
}

static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
{
 r8168dp_2_mdio_start(tp);

 r8169_mdio_write(tp, reg, value);

 r8168dp_2_mdio_stop(tp);
}

static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
{
 int value;

 /* Work around issue with chip reporting wrong PHY ID */
 if (reg == MII_PHYSID2)
  return 0xc912;

 r8168dp_2_mdio_start(tp);

 value = r8169_mdio_read(tp, reg);

 r8168dp_2_mdio_stop(tp);

 return value;
}

static void rtl_writephy(struct rtl8169_private *tp, int location, int val)
{
 switch (tp->mac_version) {
 case RTL_GIGA_MAC_VER_28:
 case RTL_GIGA_MAC_VER_31:
  r8168dp_2_mdio_write(tp, location, val);
  break;
 case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST:
  r8168g_mdio_write(tp, location, val);
  break;
 default:
  r8169_mdio_write(tp, location, val);
  break;
 }
}

static int rtl_readphy(struct rtl8169_private *tp, int location)
{
 switch (tp->mac_version) {
 case RTL_GIGA_MAC_VER_28:
 case RTL_GIGA_MAC_VER_31:
  return r8168dp_2_mdio_read(tp, location);
 case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST:
  return r8168g_mdio_read(tp, location);
 default:
  return r8169_mdio_read(tp, location);
 }
}

DECLARE_RTL_COND(rtl_ephyar_cond)
{
 return RTL_R32(tp, EPHYAR) & EPHYAR_FLAG;
}

static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
{
 RTL_W32(tp, EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
  (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);

 rtl_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);

 udelay(10);
}

static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
{
 RTL_W32(tp, EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);

 return rtl_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
  RTL_R32(tp, EPHYAR) & EPHYAR_DATA_MASK : ~0;
}

static u32 r8168dp_ocp_read(struct rtl8169_private *tp, u16 reg)
{
 RTL_W32(tp, OCPAR, 0x0fu << 12 | (reg & 0x0fff));
 return rtl_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
  RTL_R32(tp, OCPDR) : ~0;
}

static u32 r8168ep_ocp_read(struct rtl8169_private *tp, u16 reg)
{
 return _rtl_eri_read(tp, reg, ERIAR_OOB);
}

static void r8168dp_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
         u32 data)
{
 RTL_W32(tp, OCPDR, data);
 RTL_W32(tp, OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
 rtl_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
}

static void r8168ep_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
         u32 data)
{
 _rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT,
         data, ERIAR_OOB);
}

static void r8168dp_oob_notify(struct rtl8169_private *tp, u8 cmd)
{
 rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd);

 r8168dp_ocp_write(tp, 0x1, 0x30, 0x00000001);
}

#define OOB_CMD_RESET  0x00
#define OOB_CMD_DRIVER_START 0x05
#define OOB_CMD_DRIVER_STOP 0x06

static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
{
 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
}

DECLARE_RTL_COND(rtl_dp_ocp_read_cond)
{
 u16 reg;

 reg = rtl8168_get_ocp_reg(tp);

 return r8168dp_ocp_read(tp, reg) & 0x00000800;
}

DECLARE_RTL_COND(rtl_ep_ocp_read_cond)
{
 return r8168ep_ocp_read(tp, 0x124) & 0x00000001;
}

DECLARE_RTL_COND(rtl_ocp_tx_cond)
{
 return RTL_R8(tp, IBISR0) & 0x20;
}

static void rtl8168ep_stop_cmac(struct rtl8169_private *tp)
{
 RTL_W8(tp, IBCR2, RTL_R8(tp, IBCR2) & ~0x01);
 rtl_loop_wait_high(tp, &rtl_ocp_tx_cond, 50000, 2000);
 RTL_W8(tp, IBISR0, RTL_R8(tp, IBISR0) | 0x20);
 RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
}

static void rtl8168dp_driver_start(struct rtl8169_private *tp)
{
 r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START);
 if (tp->dash_enabled)
  rtl_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
}

static void rtl8168ep_driver_start(struct rtl8169_private *tp)
{
 r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
 r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
 if (tp->dash_enabled)
  rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
}

static void rtl8125bp_driver_start(struct rtl8169_private *tp)
{
 r8168ep_ocp_write(tp, 0x01, 0x14, OOB_CMD_DRIVER_START);
 r8168ep_ocp_write(tp, 0x01, 0x18, 0x00);
 r8168ep_ocp_write(tp, 0x01, 0x10, 0x01);
}

static void rtl8168_driver_start(struct rtl8169_private *tp)
{
 if (tp->dash_type == RTL_DASH_DP)
  rtl8168dp_driver_start(tp);
 else if (tp->dash_type == RTL_DASH_25_BP)
  rtl8125bp_driver_start(tp);
 else
  rtl8168ep_driver_start(tp);
}

static void rtl8168dp_driver_stop(struct rtl8169_private *tp)
{
 r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP);
 if (tp->dash_enabled)
  rtl_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
}

static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
{
 rtl8168ep_stop_cmac(tp);
 r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
 r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
 if (tp->dash_enabled)
  rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
}

static void rtl8125bp_driver_stop(struct rtl8169_private *tp)
{
 r8168ep_ocp_write(tp, 0x01, 0x14, OOB_CMD_DRIVER_STOP);
 r8168ep_ocp_write(tp, 0x01, 0x18, 0x00);
 r8168ep_ocp_write(tp, 0x01, 0x10, 0x01);
}

static void rtl8168_driver_stop(struct rtl8169_private *tp)
{
 if (tp->dash_type == RTL_DASH_DP)
  rtl8168dp_driver_stop(tp);
 else if (tp->dash_type == RTL_DASH_25_BP)
  rtl8125bp_driver_stop(tp);
 else
  rtl8168ep_driver_stop(tp);
}

static bool r8168dp_check_dash(struct rtl8169_private *tp)
{
 u16 reg = rtl8168_get_ocp_reg(tp);

 return r8168dp_ocp_read(tp, reg) & BIT(15);
}

static bool r8168ep_check_dash(struct rtl8169_private *tp)
{
 return r8168ep_ocp_read(tp, 0x128) & BIT(0);
}

static bool rtl_dash_is_enabled(struct rtl8169_private *tp)
{
 switch (tp->dash_type) {
 case RTL_DASH_DP:
  return r8168dp_check_dash(tp);
 case RTL_DASH_EP:
 case RTL_DASH_25_BP:
  return r8168ep_check_dash(tp);
 default:
  return false;
 }
}

static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)
{
 switch (tp->mac_version) {
 case RTL_GIGA_MAC_VER_28:
 case RTL_GIGA_MAC_VER_31:
  return RTL_DASH_DP;
 case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_52:
  return RTL_DASH_EP;
 case RTL_GIGA_MAC_VER_66:
  return RTL_DASH_25_BP;
 default:
  return RTL_DASH_NONE;
 }
}

static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable)
{
 if (tp->mac_version >= RTL_GIGA_MAC_VER_25 &&
     tp->mac_version != RTL_GIGA_MAC_VER_28 &&
     tp->mac_version != RTL_GIGA_MAC_VER_31 &&
     tp->mac_version != RTL_GIGA_MAC_VER_38)
  r8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, !enable);
}

static void rtl_reset_packet_filter(struct rtl8169_private *tp)
{
 rtl_eri_clear_bits(tp, 0xdc, BIT(0));
 rtl_eri_set_bits(tp, 0xdc, BIT(0));
}

DECLARE_RTL_COND(rtl_efusear_cond)
{
 return RTL_R32(tp, EFUSEAR) & EFUSEAR_FLAG;
}

u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
{
 RTL_W32(tp, EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);

 return rtl_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
  RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
}

static u32 rtl_get_events(struct rtl8169_private *tp)
{
 if (rtl_is_8125(tp))
  return RTL_R32(tp, IntrStatus_8125);
 else
  return RTL_R16(tp, IntrStatus);
}

static void rtl_ack_events(struct rtl8169_private *tp, u32 bits)
{
 if (rtl_is_8125(tp))
  RTL_W32(tp, IntrStatus_8125, bits);
 else
  RTL_W16(tp, IntrStatus, bits);
}

static void rtl_irq_disable(struct rtl8169_private *tp)
{
 if (rtl_is_8125(tp))
  RTL_W32(tp, IntrMask_8125, 0);
 else
  RTL_W16(tp, IntrMask, 0);
}

static void rtl_irq_enable(struct rtl8169_private *tp)
{
 if (rtl_is_8125(tp))
  RTL_W32(tp, IntrMask_8125, tp->irq_mask);
 else
  RTL_W16(tp, IntrMask, tp->irq_mask);
}

static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
{
 rtl_irq_disable(tp);
 rtl_ack_events(tp, 0xffffffff);
 rtl_pci_commit(tp);
}

static void rtl_link_chg_patch(struct rtl8169_private *tp)
{
 struct phy_device *phydev = tp->phydev;

 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
     tp->mac_version == RTL_GIGA_MAC_VER_38) {
  if (phydev->speed == SPEED_1000) {
   rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
   rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
  } else if (phydev->speed == SPEED_100) {
   rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
   rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
  } else {
   rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
   rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
  }
  rtl_reset_packet_filter(tp);
 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
     tp->mac_version == RTL_GIGA_MAC_VER_36) {
  if (phydev->speed == SPEED_1000) {
   rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
   rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
  } else {
   rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
   rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
  }
 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
  if (phydev->speed == SPEED_10) {
   rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02);
   rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060a);
  } else {
   rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
  }
 }
}

#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)

static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 wol->supported = WAKE_ANY;
 wol->wolopts = tp->saved_wolopts;
}

static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
{
 rtl_unlock_config_regs(tp);

 if (rtl_is_8168evl_up(tp)) {
  if (wolopts & WAKE_MAGIC)
   rtl_eri_set_bits(tp, 0x0dc, MagicPacket_v2);
  else
   rtl_eri_clear_bits(tp, 0x0dc, MagicPacket_v2);
 } else if (rtl_is_8125(tp)) {
  if (wolopts & WAKE_MAGIC)
   r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0));
  else
   r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
 } else {
  r8169_mod_reg8_cond(tp, Config3, MagicPacket,
        wolopts & WAKE_MAGIC);
 }

 r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY);
 if (rtl_is_8125(tp))
  r8168_mac_ocp_modify(tp, 0xe0c6, 0x3f,
         wolopts & WAKE_PHY ? 0x13 : 0);
 r8169_mod_reg8_cond(tp, Config5, UWF, wolopts & WAKE_UCAST);
 r8169_mod_reg8_cond(tp, Config5, BWF, wolopts & WAKE_BCAST);
 r8169_mod_reg8_cond(tp, Config5, MWF, wolopts & WAKE_MCAST);
 r8169_mod_reg8_cond(tp, Config5, LanWake, wolopts);

 switch (tp->mac_version) {
 case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
  r8169_mod_reg8_cond(tp, Config1, PMEnable, wolopts);
  break;
 case RTL_GIGA_MAC_VER_34:
 case RTL_GIGA_MAC_VER_37:
 case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_LAST:
  r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts);
  break;
 default:
  break;
 }

 rtl_lock_config_regs(tp);

 device_set_wakeup_enable(tp_to_dev(tp), wolopts);

 if (!tp->dash_enabled) {
  rtl_set_d3_pll_down(tp, !wolopts);
  tp->dev->ethtool->wol_enabled = wolopts ? 1 : 0;
 }
}

static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 if (wol->wolopts & ~WAKE_ANY)
  return -EINVAL;

 tp->saved_wolopts = wol->wolopts;
 __rtl8169_set_wol(tp, tp->saved_wolopts);

 return 0;
}

static void rtl8169_get_drvinfo(struct net_device *dev,
    struct ethtool_drvinfo *info)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 struct rtl_fw *rtl_fw = tp->rtl_fw;

 strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 strscpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
 if (rtl_fw)
  strscpy(info->fw_version, rtl_fw->version,
   sizeof(info->fw_version));
}

static int rtl8169_get_regs_len(struct net_device *dev)
{
 return R8169_REGS_SIZE;
}

static netdev_features_t rtl8169_fix_features(struct net_device *dev,
 netdev_features_t features)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 if (dev->mtu > TD_MSS_MAX)
  features &= ~NETIF_F_ALL_TSO;

 if (dev->mtu > ETH_DATA_LEN &&
     tp->mac_version > RTL_GIGA_MAC_VER_06)
  features &= ~(NETIF_F_CSUM_MASK | NETIF_F_ALL_TSO);

 return features;
}

static void rtl_set_rx_config_features(struct rtl8169_private *tp,
           netdev_features_t features)
{
 u32 rx_config = RTL_R32(tp, RxConfig);

 if (features & NETIF_F_RXALL)
  rx_config |= RX_CONFIG_ACCEPT_ERR_MASK;
 else
  rx_config &= ~RX_CONFIG_ACCEPT_ERR_MASK;

 if (rtl_is_8125(tp)) {
  if (features & NETIF_F_HW_VLAN_CTAG_RX)
   rx_config |= RX_VLAN_8125;
  else
   rx_config &= ~RX_VLAN_8125;
 }

 RTL_W32(tp, RxConfig, rx_config);
}

static int rtl8169_set_features(struct net_device *dev,
    netdev_features_t features)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 rtl_set_rx_config_features(tp, features);

 if (features & NETIF_F_RXCSUM)
  tp->cp_cmd |= RxChkSum;
 else
  tp->cp_cmd &= ~RxChkSum;

 if (!rtl_is_8125(tp)) {
  if (features & NETIF_F_HW_VLAN_CTAG_RX)
   tp->cp_cmd |= RxVlan;
  else
   tp->cp_cmd &= ~RxVlan;
 }

 RTL_W16(tp, CPlusCmd, tp->cp_cmd);
 rtl_pci_commit(tp);

 return 0;
}

static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
{
 return (skb_vlan_tag_present(skb)) ?
  TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
}

static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
{
 u32 opts2 = le32_to_cpu(desc->opts2);

 if (opts2 & RxVlanTag)
  __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff));
}

static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        void *p)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 u32 __iomem *data = tp->mmio_addr;
 u32 *dw = p;
 int i;

 for (i = 0; i < R8169_REGS_SIZE; i += 4)
  memcpy_fromio(dw++, data++, 4);
}

static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
 "tx_packets",
 "rx_packets",
 "tx_errors",
 "rx_errors",
 "rx_missed",
 "align_errors",
 "tx_single_collisions",
 "tx_multi_collisions",
 "unicast",
 "broadcast",
 "multicast",
 "tx_aborted",
 "tx_underrun",
};

static int rtl8169_get_sset_count(struct net_device *dev, int sset)
{
 switch (sset) {
 case ETH_SS_STATS:
  return ARRAY_SIZE(rtl8169_gstrings);
 default:
  return -EOPNOTSUPP;
 }
}

DECLARE_RTL_COND(rtl_counters_cond)
{
 return RTL_R32(tp, CounterAddrLow) & (CounterReset | CounterDump);
}

static void rtl8169_do_counters(struct rtl8169_private *tp, u32 counter_cmd)
{
 u32 cmd = lower_32_bits(tp->counters_phys_addr);

 RTL_W32(tp, CounterAddrHigh, upper_32_bits(tp->counters_phys_addr));
 rtl_pci_commit(tp);
 RTL_W32(tp, CounterAddrLow, cmd);
 RTL_W32(tp, CounterAddrLow, cmd | counter_cmd);

 rtl_loop_wait_low(tp, &rtl_counters_cond, 10, 1000);
}

static void rtl8169_update_counters(struct rtl8169_private *tp)
{
 u8 val = RTL_R8(tp, ChipCmd);

 /*
 * Some chips are unable to dump tally counters when the receiver
 * is disabled. If 0xff chip may be in a PCI power-save state.
 */

 if (val & CmdRxEnb && val != 0xff)
  rtl8169_do_counters(tp, CounterDump);
}

static void rtl8169_init_counter_offsets(struct rtl8169_private *tp)
{
 struct rtl8169_counters *counters = tp->counters;

 /*
 * rtl8169_init_counter_offsets is called from rtl_open.  On chip
 * versions prior to RTL_GIGA_MAC_VER_19 the tally counters are only
 * reset by a power cycle, while the counter values collected by the
 * driver are reset at every driver unload/load cycle.
 *
 * To make sure the HW values returned by @get_stats64 match the SW
 * values, we collect the initial values at first open(*) and use them
 * as offsets to normalize the values returned by @get_stats64.
 *
 * (*) We can't call rtl8169_init_counter_offsets from rtl_init_one
 * for the reason stated in rtl8169_update_counters; CmdRxEnb is only
 * set at open time by rtl_hw_start.
 */


 if (tp->tc_offset.inited)
  return;

 if (tp->mac_version >= RTL_GIGA_MAC_VER_19) {
  rtl8169_do_counters(tp, CounterReset);
 } else {
  rtl8169_update_counters(tp);
  tp->tc_offset.tx_errors = counters->tx_errors;
  tp->tc_offset.tx_multi_collision = counters->tx_multi_collision;
  tp->tc_offset.tx_aborted = counters->tx_aborted;
  tp->tc_offset.rx_missed = counters->rx_missed;
 }

 tp->tc_offset.inited = true;
}

static void rtl8169_get_ethtool_stats(struct net_device *dev,
          struct ethtool_stats *stats, u64 *data)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 struct rtl8169_counters *counters;

 counters = tp->counters;
 rtl8169_update_counters(tp);

 data[0] = le64_to_cpu(counters->tx_packets);
 data[1] = le64_to_cpu(counters->rx_packets);
 data[2] = le64_to_cpu(counters->tx_errors);
 data[3] = le32_to_cpu(counters->rx_errors);
 data[4] = le16_to_cpu(counters->rx_missed);
 data[5] = le16_to_cpu(counters->align_errors);
 data[6] = le32_to_cpu(counters->tx_one_collision);
 data[7] = le32_to_cpu(counters->tx_multi_collision);
 data[8] = le64_to_cpu(counters->rx_unicast);
 data[9] = le64_to_cpu(counters->rx_broadcast);
 data[10] = le32_to_cpu(counters->rx_multicast);
 data[11] = le16_to_cpu(counters->tx_aborted);
 data[12] = le16_to_cpu(counters->tx_underrun);
}

static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
 switch(stringset) {
 case ETH_SS_STATS:
  memcpy(data, rtl8169_gstrings, sizeof(rtl8169_gstrings));
  break;
 }
}

/*
 * Interrupt coalescing
 *
 * > 1 - the availability of the IntrMitigate (0xe2) register through the
 * >     8169, 8168 and 810x line of chipsets
 *
 * 8169, 8168, and 8136(810x) serial chipsets support it.
 *
 * > 2 - the Tx timer unit at gigabit speed
 *
 * The unit of the timer depends on both the speed and the setting of CPlusCmd
 * (0xe0) bit 1 and bit 0.
 *
 * For 8169
 * bit[1:0] \ speed        1000M           100M            10M
 * 0 0                     320ns           2.56us          40.96us
 * 0 1                     2.56us          20.48us         327.7us
 * 1 0                     5.12us          40.96us         655.4us
 * 1 1                     10.24us         81.92us         1.31ms
 *
 * For the other
 * bit[1:0] \ speed        1000M           100M            10M
 * 0 0                     5us             2.56us          40.96us
 * 0 1                     40us            20.48us         327.7us
 * 1 0                     80us            40.96us         655.4us
 * 1 1                     160us           81.92us         1.31ms
 */


/* rx/tx scale factors for all CPlusCmd[0:1] cases */
struct rtl_coalesce_info {
 u32 speed;
 u32 scale_nsecs[4];
};

/* produce array with base delay *1, *8, *8*2, *8*2*2 */
#define COALESCE_DELAY(d) { (d), 8 * (d), 16 * (d), 32 * (d) }

static const struct rtl_coalesce_info rtl_coalesce_info_8169[] = {
 { SPEED_1000, COALESCE_DELAY(320) },
 { SPEED_100, COALESCE_DELAY(2560) },
 { SPEED_10, COALESCE_DELAY(40960) },
 { 0 },
};

static const struct rtl_coalesce_info rtl_coalesce_info_8168_8136[] = {
 { SPEED_1000, COALESCE_DELAY(5000) },
 { SPEED_100, COALESCE_DELAY(2560) },
 { SPEED_10, COALESCE_DELAY(40960) },
 { 0 },
};
#undef COALESCE_DELAY

/* get rx/tx scale vector corresponding to current speed */
static const struct rtl_coalesce_info *
rtl_coalesce_info(struct rtl8169_private *tp)
{
 const struct rtl_coalesce_info *ci;

 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
  ci = rtl_coalesce_info_8169;
 else
  ci = rtl_coalesce_info_8168_8136;

 /* if speed is unknown assume highest one */
 if (tp->phydev->speed == SPEED_UNKNOWN)
  return ci;

 for (; ci->speed; ci++) {
  if (tp->phydev->speed == ci->speed)
   return ci;
 }

 return ERR_PTR(-ELNRNG);
}

static int rtl_get_coalesce(struct net_device *dev,
       struct ethtool_coalesce *ec,
       struct kernel_ethtool_coalesce *kernel_coal,
       struct netlink_ext_ack *extack)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 const struct rtl_coalesce_info *ci;
 u32 scale, c_us, c_fr;
 u16 intrmit;

 if (rtl_is_8125(tp))
  return -EOPNOTSUPP;

 memset(ec, 0, sizeof(*ec));

 /* get rx/tx scale corresponding to current speed and CPlusCmd[0:1] */
 ci = rtl_coalesce_info(tp);
 if (IS_ERR(ci))
  return PTR_ERR(ci);

 scale = ci->scale_nsecs[tp->cp_cmd & INTT_MASK];

 intrmit = RTL_R16(tp, IntrMitigate);

 c_us = FIELD_GET(RTL_COALESCE_TX_USECS, intrmit);
 ec->tx_coalesce_usecs = DIV_ROUND_UP(c_us * scale, 1000);

 c_fr = FIELD_GET(RTL_COALESCE_TX_FRAMES, intrmit);
 /* ethtool_coalesce states usecs and max_frames must not both be 0 */
 ec->tx_max_coalesced_frames = (c_us || c_fr) ? c_fr * 4 : 1;

 c_us = FIELD_GET(RTL_COALESCE_RX_USECS, intrmit);
 ec->rx_coalesce_usecs = DIV_ROUND_UP(c_us * scale, 1000);

 c_fr = FIELD_GET(RTL_COALESCE_RX_FRAMES, intrmit);
 ec->rx_max_coalesced_frames = (c_us || c_fr) ? c_fr * 4 : 1;

 return 0;
}

/* choose appropriate scale factor and CPlusCmd[0:1] for (speed, usec) */
static int rtl_coalesce_choose_scale(struct rtl8169_private *tp, u32 usec,
         u16 *cp01)
{
 const struct rtl_coalesce_info *ci;
 u16 i;

 ci = rtl_coalesce_info(tp);
 if (IS_ERR(ci))
  return PTR_ERR(ci);

 for (i = 0; i < 4; i++) {
  if (usec <= ci->scale_nsecs[i] * RTL_COALESCE_T_MAX / 1000U) {
   *cp01 = i;
   return ci->scale_nsecs[i];
  }
 }

 return -ERANGE;
}

static int rtl_set_coalesce(struct net_device *dev,
       struct ethtool_coalesce *ec,
       struct kernel_ethtool_coalesce *kernel_coal,
       struct netlink_ext_ack *extack)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 u32 tx_fr = ec->tx_max_coalesced_frames;
 u32 rx_fr = ec->rx_max_coalesced_frames;
 u32 coal_usec_max, units;
 u16 w = 0, cp01 = 0;
 int scale;

 if (rtl_is_8125(tp))
  return -EOPNOTSUPP;

 if (rx_fr > RTL_COALESCE_FRAME_MAX || tx_fr > RTL_COALESCE_FRAME_MAX)
  return -ERANGE;

 coal_usec_max = max(ec->rx_coalesce_usecs, ec->tx_coalesce_usecs);
 scale = rtl_coalesce_choose_scale(tp, coal_usec_max, &cp01);
 if (scale < 0)
  return scale;

 /* Accept max_frames=1 we returned in rtl_get_coalesce. Accept it
 * not only when usecs=0 because of e.g. the following scenario:
 *
 * - both rx_usecs=0 & rx_frames=0 in hardware (no delay on RX)
 * - rtl_get_coalesce returns rx_usecs=0, rx_frames=1
 * - then user does `ethtool -C eth0 rx-usecs 100`
 *
 * Since ethtool sends to kernel whole ethtool_coalesce settings,
 * if we want to ignore rx_frames then it has to be set to 0.
 */

 if (rx_fr == 1)
  rx_fr = 0;
 if (tx_fr == 1)
  tx_fr = 0;

 /* HW requires time limit to be set if frame limit is set */
 if ((tx_fr && !ec->tx_coalesce_usecs) ||
     (rx_fr && !ec->rx_coalesce_usecs))
  return -EINVAL;

 w |= FIELD_PREP(RTL_COALESCE_TX_FRAMES, DIV_ROUND_UP(tx_fr, 4));
 w |= FIELD_PREP(RTL_COALESCE_RX_FRAMES, DIV_ROUND_UP(rx_fr, 4));

 units = DIV_ROUND_UP(ec->tx_coalesce_usecs * 1000U, scale);
 w |= FIELD_PREP(RTL_COALESCE_TX_USECS, units);
 units = DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000U, scale);
 w |= FIELD_PREP(RTL_COALESCE_RX_USECS, units);

 RTL_W16(tp, IntrMitigate, w);

 /* Meaning of PktCntrDisable bit changed from RTL8168e-vl */
 if (rtl_is_8168evl_up(tp)) {
  if (!rx_fr && !tx_fr)
   /* disable packet counter */
   tp->cp_cmd |= PktCntrDisable;
  else
   tp->cp_cmd &= ~PktCntrDisable;
 }

 tp->cp_cmd = (tp->cp_cmd & ~INTT_MASK) | cp01;
 RTL_W16(tp, CPlusCmd, tp->cp_cmd);
 rtl_pci_commit(tp);

 return 0;
}

static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)
{
 unsigned int timer_val = READ_ONCE(tp->dev->mtu) + ETH_HLEN + 0x20;

 switch (tp->mac_version) {
 case RTL_GIGA_MAC_VER_46:
 case RTL_GIGA_MAC_VER_48:
  tp->tx_lpi_timer = timer_val;
  r8168_mac_ocp_write(tp, 0xe048, timer_val);
  break;
 case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST:
  tp->tx_lpi_timer = timer_val;
  RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val);
  break;
 default:
  break;
 }
}

static unsigned int r8169_get_tx_lpi_timer_us(struct rtl8169_private *tp)
{
 unsigned int speed = tp->phydev->speed;
 unsigned int timer = tp->tx_lpi_timer;

 if (!timer || speed == SPEED_UNKNOWN)
  return 0;

 /* tx_lpi_timer value is in bytes */
 return DIV_ROUND_CLOSEST(timer * BITS_PER_BYTE, speed);
}

static int rtl8169_get_eee(struct net_device *dev, struct ethtool_keee *data)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 int ret;

 if (!rtl_supports_eee(tp))
  return -EOPNOTSUPP;

 ret = phy_ethtool_get_eee(tp->phydev, data);
 if (ret)
  return ret;

 data->tx_lpi_timer = r8169_get_tx_lpi_timer_us(tp);

 return 0;
}

static int rtl8169_set_eee(struct net_device *dev, struct ethtool_keee *data)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 if (!rtl_supports_eee(tp))
  return -EOPNOTSUPP;

 return phy_ethtool_set_eee(tp->phydev, data);
}

static void rtl8169_get_ringparam(struct net_device *dev,
      struct ethtool_ringparam *data,
      struct kernel_ethtool_ringparam *kernel_data,
      struct netlink_ext_ack *extack)
{
 data->rx_max_pending = NUM_RX_DESC;
 data->rx_pending = NUM_RX_DESC;
 data->tx_max_pending = NUM_TX_DESC;
 data->tx_pending = NUM_TX_DESC;
}

static void rtl8169_get_pause_stats(struct net_device *dev,
        struct ethtool_pause_stats *pause_stats)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 if (!rtl_is_8125(tp))
  return;

 rtl8169_update_counters(tp);
 pause_stats->tx_pause_frames = le32_to_cpu(tp->counters->tx_pause_on);
 pause_stats->rx_pause_frames = le32_to_cpu(tp->counters->rx_pause_on);
}

static void rtl8169_get_pauseparam(struct net_device *dev,
       struct ethtool_pauseparam *data)
{
 struct rtl8169_private *tp = netdev_priv(dev);
 bool tx_pause, rx_pause;

 phy_get_pause(tp->phydev, &tx_pause, &rx_pause);

 data->autoneg = tp->phydev->autoneg;
 data->tx_pause = tx_pause ? 1 : 0;
 data->rx_pause = rx_pause ? 1 : 0;
}

static int rtl8169_set_pauseparam(struct net_device *dev,
      struct ethtool_pauseparam *data)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 if (dev->mtu > ETH_DATA_LEN)
  return -EOPNOTSUPP;

 phy_set_asym_pause(tp->phydev, data->rx_pause, data->tx_pause);

 return 0;
}

static void rtl8169_get_eth_mac_stats(struct net_device *dev,
          struct ethtool_eth_mac_stats *mac_stats)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 rtl8169_update_counters(tp);

 mac_stats->FramesTransmittedOK =
  le64_to_cpu(tp->counters->tx_packets);
 mac_stats->SingleCollisionFrames =
  le32_to_cpu(tp->counters->tx_one_collision);
 mac_stats->MultipleCollisionFrames =
  le32_to_cpu(tp->counters->tx_multi_collision);
 mac_stats->FramesReceivedOK =
  le64_to_cpu(tp->counters->rx_packets);
 mac_stats->AlignmentErrors =
  le16_to_cpu(tp->counters->align_errors);
 mac_stats->FramesLostDueToIntMACXmitError =
  le64_to_cpu(tp->counters->tx_errors);
 mac_stats->BroadcastFramesReceivedOK =
  le64_to_cpu(tp->counters->rx_broadcast);
 mac_stats->MulticastFramesReceivedOK =
  le32_to_cpu(tp->counters->rx_multicast);

 if (!rtl_is_8125(tp))
  return;

 mac_stats->AlignmentErrors =
  le32_to_cpu(tp->counters->align_errors32);
 mac_stats->OctetsTransmittedOK =
  le64_to_cpu(tp->counters->tx_octets);
 mac_stats->LateCollisions =
  le32_to_cpu(tp->counters->tx_late_collision);
 mac_stats->FramesAbortedDueToXSColls =
  le32_to_cpu(tp->counters->tx_aborted32);
 mac_stats->OctetsReceivedOK =
  le64_to_cpu(tp->counters->rx_octets);
 mac_stats->FramesLostDueToIntMACRcvError =
  le32_to_cpu(tp->counters->rx_mac_error);
 mac_stats->MulticastFramesXmittedOK =
  le64_to_cpu(tp->counters->tx_multicast64);
 mac_stats->BroadcastFramesXmittedOK =
  le64_to_cpu(tp->counters->tx_broadcast64);
 mac_stats->MulticastFramesReceivedOK =
  le64_to_cpu(tp->counters->rx_multicast64);
 mac_stats->FrameTooLongErrors =
  le32_to_cpu(tp->counters->rx_frame_too_long);
}

static void rtl8169_get_eth_ctrl_stats(struct net_device *dev,
           struct ethtool_eth_ctrl_stats *ctrl_stats)
{
 struct rtl8169_private *tp = netdev_priv(dev);

 if (!rtl_is_8125(tp))
  return;

 rtl8169_update_counters(tp);

 ctrl_stats->UnsupportedOpcodesReceived =
  le32_to_cpu(tp->counters->rx_unknown_opcode);
}

static const struct ethtool_ops rtl8169_ethtool_ops = {
 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
         ETHTOOL_COALESCE_MAX_FRAMES,
 .get_drvinfo  = rtl8169_get_drvinfo,
 .get_regs_len  = rtl8169_get_regs_len,
 .get_link  = ethtool_op_get_link,
 .get_coalesce  = rtl_get_coalesce,
 .set_coalesce  = rtl_set_coalesce,
 .get_regs  = rtl8169_get_regs,
 .get_wol  = rtl8169_get_wol,
 .set_wol  = rtl8169_set_wol,
 .get_strings  = rtl8169_get_strings,
 .get_sset_count  = rtl8169_get_sset_count,
 .get_ethtool_stats = rtl8169_get_ethtool_stats,
 .get_ts_info  = ethtool_op_get_ts_info,
 .nway_reset  = phy_ethtool_nway_reset,
 .get_eee  = rtl8169_get_eee,
 .set_eee  = rtl8169_set_eee,
 .get_link_ksettings = phy_ethtool_get_link_ksettings,
 .set_link_ksettings = phy_ethtool_set_link_ksettings,
 .get_ringparam  = rtl8169_get_ringparam,
 .get_pause_stats = rtl8169_get_pause_stats,
 .get_pauseparam  = rtl8169_get_pauseparam,
 .set_pauseparam  = rtl8169_set_pauseparam,
 .get_eth_mac_stats = rtl8169_get_eth_mac_stats,
 .get_eth_ctrl_stats = rtl8169_get_eth_ctrl_stats,
};

static const struct rtl_chip_info *rtl8169_get_chip_version(u16 xid, bool gmii)
{
 /* Chips combining a 1Gbps MAC with a 100Mbps PHY */
 static const struct rtl_chip_info rtl8106eus_info = {
  .mac_version = RTL_GIGA_MAC_VER_43,
  .name = "RTL8106eus",
  .fw_name = FIRMWARE_8106E_2,
 };
 static const struct rtl_chip_info rtl8107e_info = {
  .mac_version = RTL_GIGA_MAC_VER_48,
  .name = "RTL8107e",
  .fw_name = FIRMWARE_8107E_2,
 };
 const struct rtl_chip_info *p = rtl_chip_infos;

 while ((xid & p->mask) != p->val)
  p++;

 if (p->mac_version == RTL_GIGA_MAC_VER_42 && !gmii)
  return &rtl8106eus_info;
 if (p->mac_version == RTL_GIGA_MAC_VER_46 && !gmii)
  return &rtl8107e_info;

 return p;
}

static void rtl_release_firmware(struct rtl8169_private *tp)
{
 if (tp->rtl_fw) {
  rtl_fw_release_firmware(tp->rtl_fw);
  kfree(tp->rtl_fw);
  tp->rtl_fw = NULL;
 }
}

void r8169_apply_firmware(struct rtl8169_private *tp)
{
 int val;

 /* TODO: release firmware if rtl_fw_write_firmware signals failure. */
 if (tp->rtl_fw) {
  rtl_fw_write_firmware(tp, tp->rtl_fw);
  /* At least one firmware doesn't reset tp->ocp_base. */
  tp->ocp_base = OCP_STD_PHY_BASE;

  /* PHY soft reset may still be in progress */
  phy_read_poll_timeout(tp->phydev, MII_BMCR, val,
          !(val & BMCR_RESET),
          50000, 600000, true);
 }
}

static void rtl8168_config_eee_mac(struct rtl8169_private *tp)
{
 /* Adjust EEE LED frequency */
 if (tp->mac_version != RTL_GIGA_MAC_VER_38)
  RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);

 rtl_eri_set_bits(tp, 0x1b0, 0x0003);
}

static void rtl8125a_config_eee_mac(struct rtl8169_private *tp)
{
 r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
 r8168_mac_ocp_modify(tp, 0xeb62, 0, BIT(2) | BIT(1));
}

static void rtl8125b_config_eee_mac(struct rtl8169_private *tp)
{
 r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
}

static void rtl_rar_exgmac_set(struct rtl8169_private *tp, const u8 *addr)
{
 rtl_eri_write(tp, 0xe0, ERIAR_MASK_1111, get_unaligned_le32(addr));
 rtl_eri_write(tp, 0xe4, ERIAR_MASK_1111, get_unaligned_le16(addr + 4));
 rtl_eri_write(tp, 0xf0, ERIAR_MASK_1111, get_unaligned_le16(addr) << 16);
 rtl_eri_write(tp, 0xf4, ERIAR_MASK_1111, get_unaligned_le32(addr + 2));
}

u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp)
{
 u16 data1, data2, ioffset;

 r8168_mac_ocp_write(tp, 0xdd02, 0x807d);
 data1 = r8168_mac_ocp_read(tp, 0xdd02);
 data2 = r8168_mac_ocp_read(tp, 0xdd00);

 ioffset = (data2 >> 1) & 0x7ff8;
 ioffset |= data2 & 0x0007;
 if (data1 & BIT(7))
  ioffset |= BIT(15);

 return ioffset;
}

static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
{
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge