10Gigabit Ethernet driver for AMD SoC
This patch has the driver for 10Gigabit Ethernet controller in AMD SoC. This driver is written compatible to the Iflib framework. The existing driver is for the old version of hardware. The submitted driver here is for the recent versions of the hardware where the Ethernet controller is PCI-E based. Submitted by: Rajesh Kumar <rajesh1.kumar@amd.com> MFC after: 1 month Relnotes: yes Differential Revision: https://reviews.freebsd.org/D25793
This commit is contained in:
parent
53098f0e28
commit
7113afc84c
@ -248,6 +248,7 @@ device ixl # Intel 700 Series Physical Function
|
||||
device iavf # Intel Adaptive Virtual Function
|
||||
device ice # Intel 800 Series Physical Function
|
||||
device vmx # VMware VMXNET3 Ethernet
|
||||
device axp # AMD EPYC integrated NIC
|
||||
|
||||
# PCI Ethernet NICs.
|
||||
device bxe # Broadcom NetXtreme II BCM5771X/BCM578XX 10GbE
|
||||
|
@ -328,6 +328,7 @@ device nfe # nVidia nForce MCP on-board Ethernet
|
||||
device sfxge # Solarflare SFC9000 10Gb Ethernet
|
||||
device vmx # VMware VMXNET3 Ethernet
|
||||
device wpi # Intel 3945ABG wireless NICs.
|
||||
device axp # AMD EPYC integrated NIC
|
||||
|
||||
# IEEE 802.11 adapter firmware modules
|
||||
|
||||
|
@ -167,7 +167,7 @@ device mdio
|
||||
device mii
|
||||
device miibus # MII bus support
|
||||
device awg # Allwinner EMAC Gigabit Ethernet
|
||||
device axgbe # AMD Opteron A1100 integrated NIC
|
||||
device axa # AMD Opteron A1100 integrated NIC
|
||||
device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet
|
||||
device neta # Marvell Armada 370/38x/XP/3700 NIC
|
||||
device smc # SMSC LAN91C111
|
||||
|
@ -76,7 +76,7 @@ options PCI_IOV # PCI SR-IOV support
|
||||
# Ethernet NICs
|
||||
device mdio
|
||||
device awg # Allwinner EMAC Gigabit Ethernet
|
||||
device axgbe # AMD Opteron A1100 integrated NIC
|
||||
device axa # AMD Opteron A1100 integrated NIC
|
||||
device neta # Marvell Armada 370/38x/XP/3700 NIC
|
||||
device smc # SMSC LAN91C111
|
||||
device vnic # Cavium ThunderX NIC
|
||||
|
@ -142,6 +142,16 @@ dev/agp/agp_amd64.c optional agp
|
||||
dev/agp/agp_i810.c optional agp
|
||||
dev/agp/agp_via.c optional agp
|
||||
dev/amdgpio/amdgpio.c optional amdgpio
|
||||
dev/axgbe/if_axgbe_pci.c optional axp
|
||||
dev/axgbe/xgbe-desc.c optional axp
|
||||
dev/axgbe/xgbe-dev.c optional axp
|
||||
dev/axgbe/xgbe-drv.c optional axp
|
||||
dev/axgbe/xgbe-mdio.c optional axp
|
||||
dev/axgbe/xgbe-sysctl.c optional axp
|
||||
dev/axgbe/xgbe-txrx.c optional axp
|
||||
dev/axgbe/xgbe_osdep.c optional axp
|
||||
dev/axgbe/xgbe-i2c.c optional axp
|
||||
dev/axgbe/xgbe-phy-v2.c optional axp
|
||||
dev/hyperv/vmbus/amd64/hyperv_machdep.c optional hyperv
|
||||
dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv
|
||||
dev/ice/if_ice_iflib.c optional ice pci \
|
||||
|
@ -249,11 +249,15 @@ dev/acpica/acpi_pxm.c optional acpi
|
||||
dev/ahci/ahci_fsl_fdt.c optional SOC_NXP_LS ahci fdt
|
||||
dev/ahci/ahci_generic.c optional ahci
|
||||
dev/altera/dwc/if_dwc_socfpga.c optional fdt dwc_socfpga
|
||||
dev/axgbe/if_axgbe.c optional axgbe
|
||||
dev/axgbe/xgbe-desc.c optional axgbe
|
||||
dev/axgbe/xgbe-dev.c optional axgbe
|
||||
dev/axgbe/xgbe-drv.c optional axgbe
|
||||
dev/axgbe/xgbe-mdio.c optional axgbe
|
||||
dev/axgbe/if_axgbe.c optional axa
|
||||
dev/axgbe/xgbe-desc.c optional axa
|
||||
dev/axgbe/xgbe-dev.c optional axa
|
||||
dev/axgbe/xgbe-drv.c optional axa
|
||||
dev/axgbe/xgbe-mdio.c optional axa
|
||||
dev/axgbe/xgbe-sysctl.c optional axa
|
||||
dev/axgbe/xgbe-txrx.c optional axa
|
||||
dev/axgbe/xgbe_osdep.c optional axa
|
||||
dev/axgbe/xgbe-phy-v1.c optional axa
|
||||
dev/cpufreq/cpufreq_dt.c optional cpufreq fdt
|
||||
dev/gpio/pl061.c optional pl061 gpio
|
||||
dev/gpio/pl061_acpi.c optional pl061 gpio acpi
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2016,2017 SoftIron Inc.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This software was developed by Andrew Turner under
|
||||
* the sponsorship of SoftIron Inc.
|
||||
@ -114,6 +116,14 @@ static struct resource_spec mac_spec[] = {
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static struct xgbe_version_data xgbe_v1 = {
|
||||
.init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1,
|
||||
.xpcs_access = XGBE_XPCS_ACCESS_V1,
|
||||
.tx_max_fifo_size = 81920,
|
||||
.rx_max_fifo_size = 81920,
|
||||
.tx_tstamp_workaround = 1,
|
||||
};
|
||||
|
||||
MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data");
|
||||
|
||||
static void
|
||||
@ -135,14 +145,13 @@ axgbe_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
|
||||
{
|
||||
struct axgbe_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *)data;
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
switch(command) {
|
||||
case SIOCSIFMTU:
|
||||
if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU_JUMBO)
|
||||
error = EINVAL;
|
||||
else
|
||||
error = xgbe_change_mtu(ifp, ifr->ifr_mtu);
|
||||
/* TODO - change it to iflib way */
|
||||
break;
|
||||
case SIOCSIFFLAGS:
|
||||
error = 0;
|
||||
@ -307,6 +316,7 @@ axgbe_attach(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->prv.vdata = &xgbe_v1;
|
||||
node = ofw_bus_get_node(dev);
|
||||
if (OF_getencprop(node, "phy-handle", &phy_handle,
|
||||
sizeof(phy_handle)) <= 0) {
|
||||
@ -391,6 +401,7 @@ axgbe_attach(device_t dev)
|
||||
sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full |
|
||||
ADVERTISED_1000baseKX_Full;
|
||||
|
||||
|
||||
/*
|
||||
* Read the needed properties from the phy node.
|
||||
*/
|
||||
@ -466,13 +477,11 @@ axgbe_attach(device_t dev)
|
||||
/* Check if the NIC is DMA coherent */
|
||||
sc->prv.coherent = OF_hasprop(node, "dma-coherent");
|
||||
if (sc->prv.coherent) {
|
||||
sc->prv.axdomain = XGBE_DMA_OS_AXDOMAIN;
|
||||
sc->prv.arcache = XGBE_DMA_OS_ARCACHE;
|
||||
sc->prv.awcache = XGBE_DMA_OS_AWCACHE;
|
||||
sc->prv.arcr = XGBE_DMA_OS_ARCR;
|
||||
sc->prv.awcr = XGBE_DMA_OS_AWCR;
|
||||
} else {
|
||||
sc->prv.axdomain = XGBE_DMA_SYS_AXDOMAIN;
|
||||
sc->prv.arcache = XGBE_DMA_SYS_ARCACHE;
|
||||
sc->prv.awcache = XGBE_DMA_SYS_AWCACHE;
|
||||
sc->prv.arcr = XGBE_DMA_SYS_ARCR;
|
||||
sc->prv.awcr = XGBE_DMA_SYS_AWCR;
|
||||
}
|
||||
|
||||
/* Create the lock & workqueues */
|
||||
@ -486,6 +495,7 @@ axgbe_attach(device_t dev)
|
||||
xgbe_init_function_ptrs_phy(&sc->prv.phy_if);
|
||||
xgbe_init_function_ptrs_dev(&sc->prv.hw_if);
|
||||
xgbe_init_function_ptrs_desc(&sc->prv.desc_if);
|
||||
sc->prv.vdata->init_function_ptrs_phy_impl(&sc->prv.phy_if);
|
||||
|
||||
/* Reset the hardware */
|
||||
sc->prv.hw_if.exit(&sc->prv);
|
||||
@ -494,16 +504,14 @@ axgbe_attach(device_t dev)
|
||||
xgbe_get_all_hw_features(&sc->prv);
|
||||
|
||||
/* Set default values */
|
||||
sc->prv.pblx8 = DMA_PBL_X8_ENABLE;
|
||||
sc->prv.tx_desc_count = XGBE_TX_DESC_CNT;
|
||||
sc->prv.tx_sf_mode = MTL_TSF_ENABLE;
|
||||
sc->prv.tx_threshold = MTL_TX_THRESHOLD_64;
|
||||
sc->prv.tx_pbl = DMA_PBL_16;
|
||||
sc->prv.tx_osp_mode = DMA_OSP_ENABLE;
|
||||
sc->prv.rx_desc_count = XGBE_RX_DESC_CNT;
|
||||
sc->prv.rx_sf_mode = MTL_RSF_DISABLE;
|
||||
sc->prv.rx_threshold = MTL_RX_THRESHOLD_64;
|
||||
sc->prv.rx_pbl = DMA_PBL_16;
|
||||
sc->prv.pbl = DMA_PBL_128;
|
||||
sc->prv.pause_autoneg = 1;
|
||||
sc->prv.tx_pause = 1;
|
||||
sc->prv.rx_pause = 1;
|
||||
@ -528,7 +536,7 @@ axgbe_attach(device_t dev)
|
||||
ifp->if_softc = sc;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_ioctl = axgbe_ioctl;
|
||||
ifp->if_transmit = xgbe_xmit;
|
||||
/* TODO - change it to iflib way */
|
||||
ifp->if_qflush = axgbe_qflush;
|
||||
ifp->if_get_counter = axgbe_get_counter;
|
||||
|
||||
@ -550,11 +558,7 @@ axgbe_attach(device_t dev)
|
||||
|
||||
set_bit(XGBE_DOWN, &sc->prv.dev_state);
|
||||
|
||||
if (xgbe_open(ifp) < 0) {
|
||||
device_printf(dev, "ndo_open failed\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* TODO - change it to iflib way */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -562,6 +566,7 @@ static device_method_t axgbe_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, axgbe_probe),
|
||||
DEVMETHOD(device_attach, axgbe_attach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -569,7 +574,8 @@ static devclass_t axgbe_devclass;
|
||||
|
||||
DEFINE_CLASS_0(axgbe, axgbe_driver, axgbe_methods,
|
||||
sizeof(struct axgbe_softc));
|
||||
DRIVER_MODULE(axgbe, simplebus, axgbe_driver, axgbe_devclass, 0, 0);
|
||||
DRIVER_MODULE(axa, simplebus, axgbe_driver, axgbe_devclass, 0, 0);
|
||||
|
||||
|
||||
static struct ofw_compat_data phy_compat_data[] = {
|
||||
{ "amd,xgbe-phy-seattle-v1a", true },
|
||||
@ -605,6 +611,7 @@ static device_method_t axgbephy_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, axgbephy_probe),
|
||||
DEVMETHOD(device_attach, axgbephy_attach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
2339
sys/dev/axgbe/if_axgbe_pci.c
Normal file
2339
sys/dev/axgbe/if_axgbe_pci.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* AMD 10Gb Ethernet driver
|
||||
*
|
||||
* Copyright (c) 2014-2016,2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is available to you under your choice of the following two
|
||||
* licenses:
|
||||
*
|
||||
* License 1: GPLv2
|
||||
*
|
||||
* Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is free software; you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or (at
|
||||
@ -56,9 +56,6 @@
|
||||
*
|
||||
* License 2: Modified BSD
|
||||
*
|
||||
* Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
@ -128,52 +125,49 @@
|
||||
#define DMA_ISR 0x3008
|
||||
#define DMA_AXIARCR 0x3010
|
||||
#define DMA_AXIAWCR 0x3018
|
||||
#define DMA_AXIAWARCR 0x301c
|
||||
#define DMA_DSR0 0x3020
|
||||
#define DMA_DSR1 0x3024
|
||||
#define DMA_DSR2 0x3028
|
||||
#define DMA_DSR3 0x302C
|
||||
#define DMA_DSR4 0x3030
|
||||
#define DMA_TXEDMACR 0x3040
|
||||
#define DMA_RXEDMACR 0x3044
|
||||
|
||||
/* DMA register entry bit positions and sizes */
|
||||
#define DMA_AXIARCR_DRC_INDEX 0
|
||||
#define DMA_AXIARCR_DRC_WIDTH 4
|
||||
#define DMA_AXIARCR_DRD_INDEX 4
|
||||
#define DMA_AXIARCR_DRD_WIDTH 2
|
||||
#define DMA_AXIARCR_TEC_INDEX 8
|
||||
#define DMA_AXIARCR_TEC_WIDTH 4
|
||||
#define DMA_AXIARCR_TED_INDEX 12
|
||||
#define DMA_AXIARCR_TED_WIDTH 2
|
||||
#define DMA_AXIARCR_THC_INDEX 16
|
||||
#define DMA_AXIARCR_THC_WIDTH 4
|
||||
#define DMA_AXIARCR_THD_INDEX 20
|
||||
#define DMA_AXIARCR_THD_WIDTH 2
|
||||
#define DMA_AXIAWCR_DWC_INDEX 0
|
||||
#define DMA_AXIAWCR_DWC_WIDTH 4
|
||||
#define DMA_AXIAWCR_DWD_INDEX 4
|
||||
#define DMA_AXIAWCR_DWD_WIDTH 2
|
||||
#define DMA_AXIAWCR_RPC_INDEX 8
|
||||
#define DMA_AXIAWCR_RPC_WIDTH 4
|
||||
#define DMA_AXIAWCR_RPD_INDEX 12
|
||||
#define DMA_AXIAWCR_RPD_WIDTH 2
|
||||
#define DMA_AXIAWCR_RHC_INDEX 16
|
||||
#define DMA_AXIAWCR_RHC_WIDTH 4
|
||||
#define DMA_AXIAWCR_RHD_INDEX 20
|
||||
#define DMA_AXIAWCR_RHD_WIDTH 2
|
||||
#define DMA_AXIAWCR_TDC_INDEX 24
|
||||
#define DMA_AXIAWCR_TDC_WIDTH 4
|
||||
#define DMA_AXIAWCR_TDD_INDEX 28
|
||||
#define DMA_AXIAWCR_TDD_WIDTH 2
|
||||
#define DMA_ISR_MACIS_INDEX 17
|
||||
#define DMA_ISR_MACIS_WIDTH 1
|
||||
#define DMA_ISR_MTLIS_INDEX 16
|
||||
#define DMA_ISR_MTLIS_WIDTH 1
|
||||
#define DMA_MR_INTM_INDEX 12
|
||||
#define DMA_MR_INTM_WIDTH 2
|
||||
#define DMA_MR_SWR_INDEX 0
|
||||
#define DMA_MR_SWR_WIDTH 1
|
||||
#define DMA_RXEDMACR_RDPS_INDEX 0
|
||||
#define DMA_RXEDMACR_RDPS_WIDTH 3
|
||||
#define DMA_SBMR_AAL_INDEX 12
|
||||
#define DMA_SBMR_AAL_WIDTH 1
|
||||
#define DMA_SBMR_EAME_INDEX 11
|
||||
#define DMA_SBMR_EAME_WIDTH 1
|
||||
#define DMA_SBMR_BLEN_256_INDEX 7
|
||||
#define DMA_SBMR_BLEN_256_WIDTH 1
|
||||
#define DMA_SBMR_BLEN_INDEX 1
|
||||
#define DMA_SBMR_BLEN_WIDTH 7
|
||||
#define DMA_SBMR_RD_OSR_LMT_INDEX 16
|
||||
#define DMA_SBMR_RD_OSR_LMT_WIDTH 6
|
||||
#define DMA_SBMR_UNDEF_INDEX 0
|
||||
#define DMA_SBMR_UNDEF_WIDTH 1
|
||||
#define DMA_SBMR_WR_OSR_LMT_INDEX 24
|
||||
#define DMA_SBMR_WR_OSR_LMT_WIDTH 6
|
||||
#define DMA_TXEDMACR_TDPS_INDEX 0
|
||||
#define DMA_TXEDMACR_TDPS_WIDTH 3
|
||||
|
||||
/* DMA register values */
|
||||
#define DMA_SBMR_BLEN_256 256
|
||||
#define DMA_SBMR_BLEN_128 128
|
||||
#define DMA_SBMR_BLEN_64 64
|
||||
#define DMA_SBMR_BLEN_32 32
|
||||
#define DMA_SBMR_BLEN_16 16
|
||||
#define DMA_SBMR_BLEN_8 8
|
||||
#define DMA_SBMR_BLEN_4 4
|
||||
#define DMA_DSR_RPS_WIDTH 4
|
||||
#define DMA_DSR_TPS_WIDTH 4
|
||||
#define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH)
|
||||
@ -215,17 +209,28 @@
|
||||
#define DMA_CH_CARBR_HI 0x58
|
||||
#define DMA_CH_CARBR_LO 0x5c
|
||||
#define DMA_CH_SR 0x60
|
||||
#define DMA_CH_DSR 0x64
|
||||
#define DMA_CH_DCFL 0x68
|
||||
#define DMA_CH_MFC 0x6c
|
||||
#define DMA_CH_TDTRO 0x70
|
||||
#define DMA_CH_RDTRO 0x74
|
||||
#define DMA_CH_TDWRO 0x78
|
||||
#define DMA_CH_RDWRO 0x7C
|
||||
|
||||
/* DMA channel register entry bit positions and sizes */
|
||||
#define DMA_CH_CR_PBLX8_INDEX 16
|
||||
#define DMA_CH_CR_PBLX8_WIDTH 1
|
||||
#define DMA_CH_CR_SPH_INDEX 24
|
||||
#define DMA_CH_CR_SPH_WIDTH 1
|
||||
#define DMA_CH_IER_AIE_INDEX 15
|
||||
#define DMA_CH_IER_AIE20_INDEX 15
|
||||
#define DMA_CH_IER_AIE20_WIDTH 1
|
||||
#define DMA_CH_IER_AIE_INDEX 14
|
||||
#define DMA_CH_IER_AIE_WIDTH 1
|
||||
#define DMA_CH_IER_FBEE_INDEX 12
|
||||
#define DMA_CH_IER_FBEE_WIDTH 1
|
||||
#define DMA_CH_IER_NIE_INDEX 16
|
||||
#define DMA_CH_IER_NIE20_INDEX 16
|
||||
#define DMA_CH_IER_NIE20_WIDTH 1
|
||||
#define DMA_CH_IER_NIE_INDEX 15
|
||||
#define DMA_CH_IER_NIE_WIDTH 1
|
||||
#define DMA_CH_IER_RBUE_INDEX 7
|
||||
#define DMA_CH_IER_RBUE_WIDTH 1
|
||||
@ -291,12 +296,26 @@
|
||||
#define MAC_PFR 0x0008
|
||||
#define MAC_WTR 0x000c
|
||||
#define MAC_HTR0 0x0010
|
||||
#define MAC_HTR1 0x0014
|
||||
#define MAC_HTR2 0x0018
|
||||
#define MAC_HTR3 0x001c
|
||||
#define MAC_HTR4 0x0020
|
||||
#define MAC_HTR5 0x0024
|
||||
#define MAC_HTR6 0x0028
|
||||
#define MAC_HTR7 0x002c
|
||||
#define MAC_VLANTR 0x0050
|
||||
#define MAC_VLANHTR 0x0058
|
||||
#define MAC_VLANIR 0x0060
|
||||
#define MAC_IVLANIR 0x0064
|
||||
#define MAC_RETMR 0x006c
|
||||
#define MAC_Q0TFCR 0x0070
|
||||
#define MAC_Q1TFCR 0x0074
|
||||
#define MAC_Q2TFCR 0x0078
|
||||
#define MAC_Q3TFCR 0x007c
|
||||
#define MAC_Q4TFCR 0x0080
|
||||
#define MAC_Q5TFCR 0x0084
|
||||
#define MAC_Q6TFCR 0x0088
|
||||
#define MAC_Q7TFCR 0x008c
|
||||
#define MAC_RFCR 0x0090
|
||||
#define MAC_RQC0R 0x00a0
|
||||
#define MAC_RQC1R 0x00a4
|
||||
@ -309,11 +328,17 @@
|
||||
#define MAC_RWKPFR 0x00c4
|
||||
#define MAC_LPICSR 0x00d0
|
||||
#define MAC_LPITCR 0x00d4
|
||||
#define MAC_TIR 0x00e0
|
||||
#define MAC_VR 0x0110
|
||||
#define MAC_DR 0x0114
|
||||
#define MAC_HWF0R 0x011c
|
||||
#define MAC_HWF1R 0x0120
|
||||
#define MAC_HWF2R 0x0124
|
||||
#define MAC_MDIOSCAR 0x0200
|
||||
#define MAC_MDIOSCCDR 0x0204
|
||||
#define MAC_MDIOISR 0x0214
|
||||
#define MAC_MDIOIER 0x0218
|
||||
#define MAC_MDIOCL22R 0x0220
|
||||
#define MAC_GPIOCR 0x0278
|
||||
#define MAC_GPIOSR 0x027c
|
||||
#define MAC_MACA0HR 0x0300
|
||||
@ -370,6 +395,8 @@
|
||||
#define MAC_HWF0R_TXCOESEL_WIDTH 1
|
||||
#define MAC_HWF0R_VLHASH_INDEX 4
|
||||
#define MAC_HWF0R_VLHASH_WIDTH 1
|
||||
#define MAC_HWF0R_VXN_INDEX 29
|
||||
#define MAC_HWF0R_VXN_WIDTH 1
|
||||
#define MAC_HWF1R_ADDR64_INDEX 14
|
||||
#define MAC_HWF1R_ADDR64_WIDTH 2
|
||||
#define MAC_HWF1R_ADVTHWORD_INDEX 13
|
||||
@ -414,10 +441,32 @@
|
||||
#define MAC_ISR_MMCTXIS_WIDTH 1
|
||||
#define MAC_ISR_PMTIS_INDEX 4
|
||||
#define MAC_ISR_PMTIS_WIDTH 1
|
||||
#define MAC_ISR_SMI_INDEX 1
|
||||
#define MAC_ISR_SMI_WIDTH 1
|
||||
#define MAC_ISR_TSIS_INDEX 12
|
||||
#define MAC_ISR_TSIS_WIDTH 1
|
||||
#define MAC_MACA1HR_AE_INDEX 31
|
||||
#define MAC_MACA1HR_AE_WIDTH 1
|
||||
#define MAC_MDIOIER_SNGLCOMPIE_INDEX 12
|
||||
#define MAC_MDIOIER_SNGLCOMPIE_WIDTH 1
|
||||
#define MAC_MDIOISR_SNGLCOMPINT_INDEX 12
|
||||
#define MAC_MDIOISR_SNGLCOMPINT_WIDTH 1
|
||||
#define MAC_MDIOSCAR_DA_INDEX 21
|
||||
#define MAC_MDIOSCAR_DA_WIDTH 5
|
||||
#define MAC_MDIOSCAR_PA_INDEX 16
|
||||
#define MAC_MDIOSCAR_PA_WIDTH 5
|
||||
#define MAC_MDIOSCAR_RA_INDEX 0
|
||||
#define MAC_MDIOSCAR_RA_WIDTH 16
|
||||
#define MAC_MDIOSCCDR_BUSY_INDEX 22
|
||||
#define MAC_MDIOSCCDR_BUSY_WIDTH 1
|
||||
#define MAC_MDIOSCCDR_CMD_INDEX 16
|
||||
#define MAC_MDIOSCCDR_CMD_WIDTH 2
|
||||
#define MAC_MDIOSCCDR_CR_INDEX 19
|
||||
#define MAC_MDIOSCCDR_CR_WIDTH 3
|
||||
#define MAC_MDIOSCCDR_DATA_INDEX 0
|
||||
#define MAC_MDIOSCCDR_DATA_WIDTH 16
|
||||
#define MAC_MDIOSCCDR_SADDR_INDEX 18
|
||||
#define MAC_MDIOSCCDR_SADDR_WIDTH 1
|
||||
#define MAC_PFR_HMC_INDEX 2
|
||||
#define MAC_PFR_HMC_WIDTH 1
|
||||
#define MAC_PFR_HPF_INDEX 10
|
||||
@ -430,6 +479,8 @@
|
||||
#define MAC_PFR_PR_WIDTH 1
|
||||
#define MAC_PFR_VTFE_INDEX 16
|
||||
#define MAC_PFR_VTFE_WIDTH 1
|
||||
#define MAC_PFR_VUCC_INDEX 22
|
||||
#define MAC_PFR_VUCC_WIDTH 1
|
||||
#define MAC_PMTCSR_MGKPKTEN_INDEX 1
|
||||
#define MAC_PMTCSR_MGKPKTEN_WIDTH 1
|
||||
#define MAC_PMTCSR_PWRDWN_INDEX 0
|
||||
@ -458,6 +509,8 @@
|
||||
#define MAC_RCR_LM_WIDTH 1
|
||||
#define MAC_RCR_RE_INDEX 0
|
||||
#define MAC_RCR_RE_WIDTH 1
|
||||
#define MAC_RCR_ARPEN_INDEX 31
|
||||
#define MAC_RCR_ARPEN_WIDTH 1
|
||||
#define MAC_RFCR_PFCE_INDEX 8
|
||||
#define MAC_RFCR_PFCE_WIDTH 1
|
||||
#define MAC_RFCR_RFE_INDEX 0
|
||||
@ -492,6 +545,12 @@
|
||||
#define MAC_TCR_SS_WIDTH 2
|
||||
#define MAC_TCR_TE_INDEX 0
|
||||
#define MAC_TCR_TE_WIDTH 1
|
||||
#define MAC_TCR_VNE_INDEX 24
|
||||
#define MAC_TCR_VNE_WIDTH 1
|
||||
#define MAC_TCR_VNM_INDEX 25
|
||||
#define MAC_TCR_VNM_WIDTH 1
|
||||
#define MAC_TIR_TNID_INDEX 0
|
||||
#define MAC_TIR_TNID_WIDTH 16
|
||||
#define MAC_TSCR_AV8021ASMEN_INDEX 28
|
||||
#define MAC_TSCR_AV8021ASMEN_WIDTH 1
|
||||
#define MAC_TSCR_SNAPTYPSEL_INDEX 16
|
||||
@ -746,6 +805,8 @@
|
||||
#define MTL_FDDR 0x1010
|
||||
#define MTL_ISR 0x1020
|
||||
#define MTL_RQDCM0R 0x1030
|
||||
#define MTL_RQDCM1R 0x1034
|
||||
#define MTL_RQDCM2R 0x1038
|
||||
#define MTL_TCPM0R 0x1040
|
||||
#define MTL_TCPM1R 0x1044
|
||||
|
||||
@ -771,9 +832,13 @@
|
||||
#define MTL_Q_TQOMR 0x00
|
||||
#define MTL_Q_TQUR 0x04
|
||||
#define MTL_Q_TQDR 0x08
|
||||
#define MTL_Q_TC0ETSCR 0x10
|
||||
#define MTL_Q_TC0ETSSR 0x14
|
||||
#define MTL_Q_TC0QWR 0x18
|
||||
#define MTL_Q_RQOMR 0x40
|
||||
#define MTL_Q_RQMPOCR 0x44
|
||||
#define MTL_Q_RQDR 0x48
|
||||
#define MTL_Q_RQCR 0x4c
|
||||
#define MTL_Q_RQFCR 0x50
|
||||
#define MTL_Q_IER 0x70
|
||||
#define MTL_Q_ISR 0x74
|
||||
@ -795,6 +860,10 @@
|
||||
#define MTL_Q_RQOMR_RSF_WIDTH 1
|
||||
#define MTL_Q_RQOMR_RTC_INDEX 0
|
||||
#define MTL_Q_RQOMR_RTC_WIDTH 2
|
||||
#define MTL_Q_TQDR_TRCSTS_INDEX 1
|
||||
#define MTL_Q_TQDR_TRCSTS_WIDTH 2
|
||||
#define MTL_Q_TQDR_TXQSTS_INDEX 4
|
||||
#define MTL_Q_TQDR_TXQSTS_WIDTH 1
|
||||
#define MTL_Q_TQOMR_FTQ_INDEX 0
|
||||
#define MTL_Q_TQOMR_FTQ_WIDTH 1
|
||||
#define MTL_Q_TQOMR_Q2TCMAP_INDEX 8
|
||||
@ -864,7 +933,17 @@
|
||||
* an address phase and a data phase. The address phases requires
|
||||
* writing an address selection value to the MMD select regiesters.
|
||||
*/
|
||||
#define PCS_MMD_SELECT 0xff
|
||||
#define PCS_V1_WINDOW_SELECT 0x03fc
|
||||
#define PCS_V2_WINDOW_DEF 0x9060
|
||||
#define PCS_V2_WINDOW_SELECT 0x9064
|
||||
#define PCS_V2_RV_WINDOW_DEF 0x1060
|
||||
#define PCS_V2_RV_WINDOW_SELECT 0x1064
|
||||
|
||||
/* PCS register entry bit positions and sizes */
|
||||
#define PCS_V2_WINDOW_DEF_OFFSET_INDEX 6
|
||||
#define PCS_V2_WINDOW_DEF_OFFSET_WIDTH 14
|
||||
#define PCS_V2_WINDOW_DEF_SIZE_INDEX 2
|
||||
#define PCS_V2_WINDOW_DEF_SIZE_WIDTH 4
|
||||
|
||||
/* SerDes integration register offsets */
|
||||
#define SIR0_KR_RT_1 0x002c
|
||||
@ -908,6 +987,199 @@
|
||||
#define RXTX_REG129_RXDFE_CONFIG_INDEX 14
|
||||
#define RXTX_REG129_RXDFE_CONFIG_WIDTH 2
|
||||
|
||||
/* MAC Control register offsets */
|
||||
#define XP_PROP_0 0x0000
|
||||
#define XP_PROP_1 0x0004
|
||||
#define XP_PROP_2 0x0008
|
||||
#define XP_PROP_3 0x000c
|
||||
#define XP_PROP_4 0x0010
|
||||
#define XP_PROP_5 0x0014
|
||||
#define XP_MAC_ADDR_LO 0x0020
|
||||
#define XP_MAC_ADDR_HI 0x0024
|
||||
#define XP_ECC_ISR 0x0030
|
||||
#define XP_ECC_IER 0x0034
|
||||
#define XP_ECC_CNT0 0x003c
|
||||
#define XP_ECC_CNT1 0x0040
|
||||
#define XP_DRIVER_INT_REQ 0x0060
|
||||
#define XP_DRIVER_INT_RO 0x0064
|
||||
#define XP_DRIVER_SCRATCH_0 0x0068
|
||||
#define XP_DRIVER_SCRATCH_1 0x006c
|
||||
#define XP_INT_REISSUE_EN 0x0074
|
||||
#define XP_INT_EN 0x0078
|
||||
#define XP_I2C_MUTEX 0x0080
|
||||
#define XP_MDIO_MUTEX 0x0084
|
||||
|
||||
/* MAC Control register entry bit positions and sizes */
|
||||
#define XP_DRIVER_INT_REQ_REQUEST_INDEX 0
|
||||
#define XP_DRIVER_INT_REQ_REQUEST_WIDTH 1
|
||||
#define XP_DRIVER_INT_RO_STATUS_INDEX 0
|
||||
#define XP_DRIVER_INT_RO_STATUS_WIDTH 1
|
||||
#define XP_DRIVER_SCRATCH_0_COMMAND_INDEX 0
|
||||
#define XP_DRIVER_SCRATCH_0_COMMAND_WIDTH 8
|
||||
#define XP_DRIVER_SCRATCH_0_SUB_COMMAND_INDEX 8
|
||||
#define XP_DRIVER_SCRATCH_0_SUB_COMMAND_WIDTH 8
|
||||
#define XP_ECC_CNT0_RX_DED_INDEX 24
|
||||
#define XP_ECC_CNT0_RX_DED_WIDTH 8
|
||||
#define XP_ECC_CNT0_RX_SEC_INDEX 16
|
||||
#define XP_ECC_CNT0_RX_SEC_WIDTH 8
|
||||
#define XP_ECC_CNT0_TX_DED_INDEX 8
|
||||
#define XP_ECC_CNT0_TX_DED_WIDTH 8
|
||||
#define XP_ECC_CNT0_TX_SEC_INDEX 0
|
||||
#define XP_ECC_CNT0_TX_SEC_WIDTH 8
|
||||
#define XP_ECC_CNT1_DESC_DED_INDEX 8
|
||||
#define XP_ECC_CNT1_DESC_DED_WIDTH 8
|
||||
#define XP_ECC_CNT1_DESC_SEC_INDEX 0
|
||||
#define XP_ECC_CNT1_DESC_SEC_WIDTH 8
|
||||
#define XP_ECC_IER_DESC_DED_INDEX 5
|
||||
#define XP_ECC_IER_DESC_DED_WIDTH 1
|
||||
#define XP_ECC_IER_DESC_SEC_INDEX 4
|
||||
#define XP_ECC_IER_DESC_SEC_WIDTH 1
|
||||
#define XP_ECC_IER_RX_DED_INDEX 3
|
||||
#define XP_ECC_IER_RX_DED_WIDTH 1
|
||||
#define XP_ECC_IER_RX_SEC_INDEX 2
|
||||
#define XP_ECC_IER_RX_SEC_WIDTH 1
|
||||
#define XP_ECC_IER_TX_DED_INDEX 1
|
||||
#define XP_ECC_IER_TX_DED_WIDTH 1
|
||||
#define XP_ECC_IER_TX_SEC_INDEX 0
|
||||
#define XP_ECC_IER_TX_SEC_WIDTH 1
|
||||
#define XP_ECC_ISR_DESC_DED_INDEX 5
|
||||
#define XP_ECC_ISR_DESC_DED_WIDTH 1
|
||||
#define XP_ECC_ISR_DESC_SEC_INDEX 4
|
||||
#define XP_ECC_ISR_DESC_SEC_WIDTH 1
|
||||
#define XP_ECC_ISR_RX_DED_INDEX 3
|
||||
#define XP_ECC_ISR_RX_DED_WIDTH 1
|
||||
#define XP_ECC_ISR_RX_SEC_INDEX 2
|
||||
#define XP_ECC_ISR_RX_SEC_WIDTH 1
|
||||
#define XP_ECC_ISR_TX_DED_INDEX 1
|
||||
#define XP_ECC_ISR_TX_DED_WIDTH 1
|
||||
#define XP_ECC_ISR_TX_SEC_INDEX 0
|
||||
#define XP_ECC_ISR_TX_SEC_WIDTH 1
|
||||
#define XP_I2C_MUTEX_BUSY_INDEX 31
|
||||
#define XP_I2C_MUTEX_BUSY_WIDTH 1
|
||||
#define XP_I2C_MUTEX_ID_INDEX 29
|
||||
#define XP_I2C_MUTEX_ID_WIDTH 2
|
||||
#define XP_I2C_MUTEX_ACTIVE_INDEX 0
|
||||
#define XP_I2C_MUTEX_ACTIVE_WIDTH 1
|
||||
#define XP_MAC_ADDR_HI_VALID_INDEX 31
|
||||
#define XP_MAC_ADDR_HI_VALID_WIDTH 1
|
||||
#define XP_PROP_0_CONN_TYPE_INDEX 28
|
||||
#define XP_PROP_0_CONN_TYPE_WIDTH 3
|
||||
#define XP_PROP_0_MDIO_ADDR_INDEX 16
|
||||
#define XP_PROP_0_MDIO_ADDR_WIDTH 5
|
||||
#define XP_PROP_0_PORT_ID_INDEX 0
|
||||
#define XP_PROP_0_PORT_ID_WIDTH 8
|
||||
#define XP_PROP_0_PORT_MODE_INDEX 8
|
||||
#define XP_PROP_0_PORT_MODE_WIDTH 4
|
||||
#define XP_PROP_0_PORT_SPEEDS_INDEX 23
|
||||
#define XP_PROP_0_PORT_SPEEDS_WIDTH 4
|
||||
#define XP_PROP_1_MAX_RX_DMA_INDEX 24
|
||||
#define XP_PROP_1_MAX_RX_DMA_WIDTH 5
|
||||
#define XP_PROP_1_MAX_RX_QUEUES_INDEX 8
|
||||
#define XP_PROP_1_MAX_RX_QUEUES_WIDTH 5
|
||||
#define XP_PROP_1_MAX_TX_DMA_INDEX 16
|
||||
#define XP_PROP_1_MAX_TX_DMA_WIDTH 5
|
||||
#define XP_PROP_1_MAX_TX_QUEUES_INDEX 0
|
||||
#define XP_PROP_1_MAX_TX_QUEUES_WIDTH 5
|
||||
#define XP_PROP_2_RX_FIFO_SIZE_INDEX 16
|
||||
#define XP_PROP_2_RX_FIFO_SIZE_WIDTH 16
|
||||
#define XP_PROP_2_TX_FIFO_SIZE_INDEX 0
|
||||
#define XP_PROP_2_TX_FIFO_SIZE_WIDTH 16
|
||||
#define XP_PROP_3_GPIO_MASK_INDEX 28
|
||||
#define XP_PROP_3_GPIO_MASK_WIDTH 4
|
||||
#define XP_PROP_3_GPIO_MOD_ABS_INDEX 20
|
||||
#define XP_PROP_3_GPIO_MOD_ABS_WIDTH 4
|
||||
#define XP_PROP_3_GPIO_RATE_SELECT_INDEX 16
|
||||
#define XP_PROP_3_GPIO_RATE_SELECT_WIDTH 4
|
||||
#define XP_PROP_3_GPIO_RX_LOS_INDEX 24
|
||||
#define XP_PROP_3_GPIO_RX_LOS_WIDTH 4
|
||||
#define XP_PROP_3_GPIO_TX_FAULT_INDEX 12
|
||||
#define XP_PROP_3_GPIO_TX_FAULT_WIDTH 4
|
||||
#define XP_PROP_3_GPIO_ADDR_INDEX 8
|
||||
#define XP_PROP_3_GPIO_ADDR_WIDTH 3
|
||||
#define XP_PROP_3_MDIO_RESET_INDEX 0
|
||||
#define XP_PROP_3_MDIO_RESET_WIDTH 2
|
||||
#define XP_PROP_3_MDIO_RESET_I2C_ADDR_INDEX 8
|
||||
#define XP_PROP_3_MDIO_RESET_I2C_ADDR_WIDTH 3
|
||||
#define XP_PROP_3_MDIO_RESET_I2C_GPIO_INDEX 12
|
||||
#define XP_PROP_3_MDIO_RESET_I2C_GPIO_WIDTH 4
|
||||
#define XP_PROP_3_MDIO_RESET_INT_GPIO_INDEX 4
|
||||
#define XP_PROP_3_MDIO_RESET_INT_GPIO_WIDTH 2
|
||||
#define XP_PROP_4_MUX_ADDR_HI_INDEX 8
|
||||
#define XP_PROP_4_MUX_ADDR_HI_WIDTH 5
|
||||
#define XP_PROP_4_MUX_ADDR_LO_INDEX 0
|
||||
#define XP_PROP_4_MUX_ADDR_LO_WIDTH 3
|
||||
#define XP_PROP_4_MUX_CHAN_INDEX 4
|
||||
#define XP_PROP_4_MUX_CHAN_WIDTH 3
|
||||
#define XP_PROP_4_REDRV_ADDR_INDEX 16
|
||||
#define XP_PROP_4_REDRV_ADDR_WIDTH 7
|
||||
#define XP_PROP_4_REDRV_IF_INDEX 23
|
||||
#define XP_PROP_4_REDRV_IF_WIDTH 1
|
||||
#define XP_PROP_4_REDRV_LANE_INDEX 24
|
||||
#define XP_PROP_4_REDRV_LANE_WIDTH 3
|
||||
#define XP_PROP_4_REDRV_MODEL_INDEX 28
|
||||
#define XP_PROP_4_REDRV_MODEL_WIDTH 3
|
||||
#define XP_PROP_4_REDRV_PRESENT_INDEX 31
|
||||
#define XP_PROP_4_REDRV_PRESENT_WIDTH 1
|
||||
|
||||
/* I2C Control register offsets */
|
||||
#define IC_CON 0x0000
|
||||
#define IC_TAR 0x0004
|
||||
#define IC_DATA_CMD 0x0010
|
||||
#define IC_INTR_STAT 0x002c
|
||||
#define IC_INTR_MASK 0x0030
|
||||
#define IC_RAW_INTR_STAT 0x0034
|
||||
#define IC_CLR_INTR 0x0040
|
||||
#define IC_CLR_TX_ABRT 0x0054
|
||||
#define IC_CLR_STOP_DET 0x0060
|
||||
#define IC_ENABLE 0x006c
|
||||
#define IC_TXFLR 0x0074
|
||||
#define IC_RXFLR 0x0078
|
||||
#define IC_TX_ABRT_SOURCE 0x0080
|
||||
#define IC_ENABLE_STATUS 0x009c
|
||||
#define IC_COMP_PARAM_1 0x00f4
|
||||
|
||||
/* I2C Control register entry bit positions and sizes */
|
||||
#define IC_COMP_PARAM_1_MAX_SPEED_MODE_INDEX 2
|
||||
#define IC_COMP_PARAM_1_MAX_SPEED_MODE_WIDTH 2
|
||||
#define IC_COMP_PARAM_1_RX_BUFFER_DEPTH_INDEX 8
|
||||
#define IC_COMP_PARAM_1_RX_BUFFER_DEPTH_WIDTH 8
|
||||
#define IC_COMP_PARAM_1_TX_BUFFER_DEPTH_INDEX 16
|
||||
#define IC_COMP_PARAM_1_TX_BUFFER_DEPTH_WIDTH 8
|
||||
#define IC_CON_MASTER_MODE_INDEX 0
|
||||
#define IC_CON_MASTER_MODE_WIDTH 1
|
||||
#define IC_CON_RESTART_EN_INDEX 5
|
||||
#define IC_CON_RESTART_EN_WIDTH 1
|
||||
#define IC_CON_RX_FIFO_FULL_HOLD_INDEX 9
|
||||
#define IC_CON_RX_FIFO_FULL_HOLD_WIDTH 1
|
||||
#define IC_CON_SLAVE_DISABLE_INDEX 6
|
||||
#define IC_CON_SLAVE_DISABLE_WIDTH 1
|
||||
#define IC_CON_SPEED_INDEX 1
|
||||
#define IC_CON_SPEED_WIDTH 2
|
||||
#define IC_DATA_CMD_CMD_INDEX 8
|
||||
#define IC_DATA_CMD_CMD_WIDTH 1
|
||||
#define IC_DATA_CMD_STOP_INDEX 9
|
||||
#define IC_DATA_CMD_STOP_WIDTH 1
|
||||
#define IC_ENABLE_ABORT_INDEX 1
|
||||
#define IC_ENABLE_ABORT_WIDTH 1
|
||||
#define IC_ENABLE_EN_INDEX 0
|
||||
#define IC_ENABLE_EN_WIDTH 1
|
||||
#define IC_ENABLE_STATUS_EN_INDEX 0
|
||||
#define IC_ENABLE_STATUS_EN_WIDTH 1
|
||||
#define IC_INTR_MASK_TX_EMPTY_INDEX 4
|
||||
#define IC_INTR_MASK_TX_EMPTY_WIDTH 1
|
||||
#define IC_RAW_INTR_STAT_RX_FULL_INDEX 2
|
||||
#define IC_RAW_INTR_STAT_RX_FULL_WIDTH 1
|
||||
#define IC_RAW_INTR_STAT_STOP_DET_INDEX 9
|
||||
#define IC_RAW_INTR_STAT_STOP_DET_WIDTH 1
|
||||
#define IC_RAW_INTR_STAT_TX_ABRT_INDEX 6
|
||||
#define IC_RAW_INTR_STAT_TX_ABRT_WIDTH 1
|
||||
#define IC_RAW_INTR_STAT_TX_EMPTY_INDEX 4
|
||||
#define IC_RAW_INTR_STAT_TX_EMPTY_WIDTH 1
|
||||
|
||||
/* I2C Control register value */
|
||||
#define IC_TX_ABRT_7B_ADDR_NOACK 0x0001
|
||||
#define IC_TX_ABRT_ARB_LOST 0x1000
|
||||
|
||||
/* Descriptor/Packet entry bit positions and sizes */
|
||||
#define RX_PACKET_ERRORS_CRC_INDEX 2
|
||||
#define RX_PACKET_ERRORS_CRC_WIDTH 1
|
||||
@ -922,8 +1194,8 @@
|
||||
#define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1
|
||||
#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2
|
||||
#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_LAST_INDEX 2
|
||||
#define RX_PACKET_ATTRIBUTES_LAST_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3
|
||||
#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4
|
||||
@ -932,11 +1204,21 @@
|
||||
#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6
|
||||
#define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7
|
||||
#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_TNP_INDEX 8
|
||||
#define RX_PACKET_ATTRIBUTES_TNP_WIDTH 1
|
||||
#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_INDEX 9
|
||||
#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_WIDTH 1
|
||||
|
||||
#define RX_NORMAL_DESC0_OVT_INDEX 0
|
||||
#define RX_NORMAL_DESC0_OVT_WIDTH 16
|
||||
#define RX_NORMAL_DESC2_HL_INDEX 0
|
||||
#define RX_NORMAL_DESC2_HL_WIDTH 10
|
||||
#define RX_NORMAL_DESC2_TNP_INDEX 11
|
||||
#define RX_NORMAL_DESC2_TNP_WIDTH 1
|
||||
#define RX_NORMAL_DESC2_RPNG_INDEX 14
|
||||
#define RX_NORMAL_DESC2_RPNG_WIDTH 1
|
||||
#define RX_NORMAL_DESC3_CDA_INDEX 27
|
||||
#define RX_NORMAL_DESC3_CDA_WIDTH 1
|
||||
#define RX_NORMAL_DESC3_CTXT_INDEX 30
|
||||
@ -963,9 +1245,11 @@
|
||||
#define RX_DESC3_L34T_IPV4_TCP 1
|
||||
#define RX_DESC3_L34T_IPV4_UDP 2
|
||||
#define RX_DESC3_L34T_IPV4_ICMP 3
|
||||
#define RX_DESC3_L34T_IPV4_UNKNOWN 7
|
||||
#define RX_DESC3_L34T_IPV6_TCP 9
|
||||
#define RX_DESC3_L34T_IPV6_UDP 10
|
||||
#define RX_DESC3_L34T_IPV6_ICMP 11
|
||||
#define RX_DESC3_L34T_IPV6_UNKNOWN 15
|
||||
|
||||
#define RX_CONTEXT_DESC3_TSA_INDEX 4
|
||||
#define RX_CONTEXT_DESC3_TSA_WIDTH 1
|
||||
@ -980,6 +1264,8 @@
|
||||
#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1
|
||||
#define TX_PACKET_ATTRIBUTES_PTP_INDEX 3
|
||||
#define TX_PACKET_ATTRIBUTES_PTP_WIDTH 1
|
||||
#define TX_PACKET_ATTRIBUTES_VXLAN_INDEX 4
|
||||
#define TX_PACKET_ATTRIBUTES_VXLAN_WIDTH 1
|
||||
|
||||
#define TX_CONTEXT_DESC2_MSS_INDEX 0
|
||||
#define TX_CONTEXT_DESC2_MSS_WIDTH 15
|
||||
@ -1020,8 +1306,11 @@
|
||||
#define TX_NORMAL_DESC3_TCPPL_WIDTH 18
|
||||
#define TX_NORMAL_DESC3_TSE_INDEX 18
|
||||
#define TX_NORMAL_DESC3_TSE_WIDTH 1
|
||||
#define TX_NORMAL_DESC3_VNP_INDEX 23
|
||||
#define TX_NORMAL_DESC3_VNP_WIDTH 3
|
||||
|
||||
#define TX_NORMAL_DESC2_VLAN_INSERT 0x2
|
||||
#define TX_NORMAL_DESC3_VXLAN_PACKET 0x3
|
||||
|
||||
/* MDIO undefined or vendor specific registers */
|
||||
#ifndef MDIO_PMA_10GBR_PMD_CTRL
|
||||
@ -1032,6 +1321,10 @@
|
||||
#define MDIO_PMA_10GBR_FECCTRL 0x00ab
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_PCS_DIG_CTRL
|
||||
#define MDIO_PCS_DIG_CTRL 0x8000
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_XNP
|
||||
#define MDIO_AN_XNP 0x0016
|
||||
#endif
|
||||
@ -1052,11 +1345,52 @@
|
||||
#define MDIO_AN_INT 0x8002
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_AN_ADVERTISE
|
||||
#define MDIO_VEND2_AN_ADVERTISE 0x0004
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_AN_LP_ABILITY
|
||||
#define MDIO_VEND2_AN_LP_ABILITY 0x0005
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_AN_CTRL
|
||||
#define MDIO_VEND2_AN_CTRL 0x8001
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_AN_STAT
|
||||
#define MDIO_VEND2_AN_STAT 0x8002
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_PMA_CDR_CONTROL
|
||||
#define MDIO_VEND2_PMA_CDR_CONTROL 0x8056
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_CTRL1_SPEED1G
|
||||
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_CTRL1_AN_ENABLE
|
||||
#define MDIO_VEND2_CTRL1_AN_ENABLE BIT(12)
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_CTRL1_AN_RESTART
|
||||
#define MDIO_VEND2_CTRL1_AN_RESTART BIT(9)
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_CTRL1_SS6
|
||||
#define MDIO_VEND2_CTRL1_SS6 BIT(6)
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_VEND2_CTRL1_SS13
|
||||
#define MDIO_VEND2_CTRL1_SS13 BIT(13)
|
||||
#endif
|
||||
|
||||
/* MDIO mask values */
|
||||
#define XGBE_AN_CL73_INT_CMPLT BIT(0)
|
||||
#define XGBE_AN_CL73_INC_LINK BIT(1)
|
||||
#define XGBE_AN_CL73_PG_RCV BIT(2)
|
||||
#define XGBE_AN_CL73_INT_MASK 0x07
|
||||
|
||||
#define XGBE_XNP_MCF_NULL_MESSAGE 0x001
|
||||
#define XGBE_XNP_ACK_PROCESSED BIT(12)
|
||||
#define XGBE_XNP_MP_FORMATTED BIT(13)
|
||||
@ -1065,6 +1399,24 @@
|
||||
#define XGBE_KR_TRAINING_START BIT(0)
|
||||
#define XGBE_KR_TRAINING_ENABLE BIT(1)
|
||||
|
||||
#define XGBE_PCS_CL37_BP BIT(12)
|
||||
|
||||
#define XGBE_AN_CL37_INT_CMPLT BIT(0)
|
||||
#define XGBE_AN_CL37_INT_MASK 0x01
|
||||
|
||||
#define XGBE_AN_CL37_HD_MASK 0x40
|
||||
#define XGBE_AN_CL37_FD_MASK 0x20
|
||||
|
||||
#define XGBE_AN_CL37_PCS_MODE_MASK 0x06
|
||||
#define XGBE_AN_CL37_PCS_MODE_BASEX 0x00
|
||||
#define XGBE_AN_CL37_PCS_MODE_SGMII 0x04
|
||||
#define XGBE_AN_CL37_TX_CONFIG_MASK 0x08
|
||||
#define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100
|
||||
|
||||
#define XGBE_PMA_CDR_TRACK_EN_MASK 0x01
|
||||
#define XGBE_PMA_CDR_TRACK_EN_OFF 0x00
|
||||
#define XGBE_PMA_CDR_TRACK_EN_ON 0x01
|
||||
|
||||
/* Bit setting and getting macros
|
||||
* The get macro will extract the current bit field value from within
|
||||
* the variable
|
||||
@ -1140,7 +1492,7 @@ do { \
|
||||
|
||||
#define XGMAC_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u32 reg_val = XGMAC_IOREAD((_pdata), _reg); \
|
||||
uint32_t reg_val = XGMAC_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
@ -1166,7 +1518,7 @@ do { \
|
||||
|
||||
#define XGMAC_MTL_IOWRITE_BITS(_pdata, _n, _reg, _field, _val) \
|
||||
do { \
|
||||
u32 reg_val = XGMAC_MTL_IOREAD((_pdata), (_n), _reg); \
|
||||
uint32_t reg_val = XGMAC_MTL_IOREAD((_pdata), (_n), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
@ -1191,7 +1543,7 @@ do { \
|
||||
|
||||
#define XGMAC_DMA_IOWRITE_BITS(_channel, _reg, _field, _val) \
|
||||
do { \
|
||||
u32 reg_val = XGMAC_DMA_IOREAD((_channel), _reg); \
|
||||
uint32_t reg_val = XGMAC_DMA_IOREAD((_channel), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
@ -1201,12 +1553,28 @@ do { \
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* within the register values of XPCS registers.
|
||||
*/
|
||||
#define XPCS_IOWRITE(_pdata, _off, _val) \
|
||||
#define XPCS_GET_BITS(_var, _prefix, _field) \
|
||||
GET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH)
|
||||
|
||||
#define XPCS_SET_BITS(_var, _prefix, _field, _val) \
|
||||
SET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH, (_val))
|
||||
|
||||
#define XPCS32_IOWRITE(_pdata, _off, _val) \
|
||||
bus_write_4((_pdata)->xpcs_res, (_off), _val)
|
||||
|
||||
#define XPCS_IOREAD(_pdata, _off) \
|
||||
#define XPCS32_IOREAD(_pdata, _off) \
|
||||
bus_read_4((_pdata)->xpcs_res, (_off))
|
||||
|
||||
#define XPCS16_IOWRITE(_pdata, _off, _val) \
|
||||
bus_write_2((_pdata)->xpcs_res, (_off), _val)
|
||||
|
||||
#define XPCS16_IOREAD(_pdata, _off) \
|
||||
bus_read_2((_pdata)->xpcs_res, (_off))
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* within the register values of SerDes integration registers.
|
||||
*/
|
||||
@ -1233,7 +1601,7 @@ do { \
|
||||
|
||||
#define XSIR0_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u16 reg_val = XSIR0_IOREAD((_pdata), _reg); \
|
||||
uint16_t reg_val = XSIR0_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
@ -1253,7 +1621,7 @@ do { \
|
||||
|
||||
#define XSIR1_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u16 reg_val = XSIR1_IOREAD((_pdata), _reg); \
|
||||
uint16_t reg_val = XSIR1_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
@ -1276,13 +1644,81 @@ do { \
|
||||
|
||||
#define XRXTX_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u16 reg_val = XRXTX_IOREAD((_pdata), _reg); \
|
||||
uint16_t reg_val = XRXTX_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
XRXTX_IOWRITE((_pdata), _reg, reg_val); \
|
||||
} while (0)
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* within the register values of MAC Control registers.
|
||||
*/
|
||||
#define XP_GET_BITS(_var, _prefix, _field) \
|
||||
GET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH)
|
||||
|
||||
#define XP_SET_BITS(_var, _prefix, _field, _val) \
|
||||
SET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH, (_val))
|
||||
|
||||
#define XP_IOREAD(_pdata, _reg) \
|
||||
bus_read_4((_pdata)->xgmac_res, _reg + XGBE_MAC_PROP_OFFSET)
|
||||
|
||||
#define XP_IOREAD_BITS(_pdata, _reg, _field) \
|
||||
GET_BITS(XP_IOREAD((_pdata), (_reg)), \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH)
|
||||
|
||||
#define XP_IOWRITE(_pdata, _reg, _val) \
|
||||
bus_write_4((_pdata)->xgmac_res, _reg + XGBE_MAC_PROP_OFFSET, \
|
||||
(_val))
|
||||
|
||||
#define XP_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
uint32_t reg_val = XP_IOREAD((_pdata), (_reg)); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
XP_IOWRITE((_pdata), (_reg), reg_val); \
|
||||
} while (0)
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* within the register values of I2C Control registers.
|
||||
*/
|
||||
#define XI2C_GET_BITS(_var, _prefix, _field) \
|
||||
GET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH)
|
||||
|
||||
#define XI2C_SET_BITS(_var, _prefix, _field, _val) \
|
||||
SET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH, (_val))
|
||||
|
||||
#define XI2C_IOREAD(_pdata, _reg) \
|
||||
bus_read_4((_pdata)->xgmac_res, _reg + XGBE_I2C_CTRL_OFFSET)
|
||||
|
||||
#define XI2C_IOREAD_BITS(_pdata, _reg, _field) \
|
||||
GET_BITS(XI2C_IOREAD((_pdata), (_reg)), \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH)
|
||||
|
||||
#define XI2C_IOWRITE(_pdata, _reg, _val) \
|
||||
bus_write_4((_pdata)->xgmac_res, _reg + XGBE_I2C_CTRL_OFFSET, \
|
||||
(_val))
|
||||
|
||||
#define XI2C_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
uint32_t reg_val = XI2C_IOREAD((_pdata), (_reg)); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
XI2C_IOWRITE((_pdata), (_reg), reg_val); \
|
||||
} while (0)
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* using MDIO. Different from above because of the use of standardized
|
||||
* Linux include values. No shifting is performed with the bit
|
||||
@ -1301,7 +1737,7 @@ do { \
|
||||
|
||||
#define XMDIO_WRITE_BITS(_pdata, _mmd, _reg, _mask, _val) \
|
||||
do { \
|
||||
u32 mmd_val = XMDIO_READ((_pdata), _mmd, _reg); \
|
||||
uint32_t mmd_val = XMDIO_READ((_pdata), _mmd, _reg); \
|
||||
mmd_val &= ~_mask; \
|
||||
mmd_val |= (_val); \
|
||||
XMDIO_WRITE((_pdata), _mmd, _reg, mmd_val); \
|
||||
|
272
sys/dev/axgbe/xgbe-dcb.c
Normal file
272
sys/dev/axgbe/xgbe-dcb.c
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* AMD 10Gb Ethernet driver
|
||||
*
|
||||
* This file is available to you under your choice of the following two
|
||||
* licenses:
|
||||
*
|
||||
* License 1: GPLv2
|
||||
*
|
||||
* Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is free software; you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* License 2: Modified BSD
|
||||
*
|
||||
* Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Advanced Micro Devices, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "xgbe.h"
|
||||
|
||||
#if 0
|
||||
static int xgbe_dcb_ieee_getets(struct xgbe_prv_data *pdata,
|
||||
struct ieee_ets *ets)
|
||||
{
|
||||
/* Set number of supported traffic classes */
|
||||
ets->ets_cap = pdata->hw_feat.tc_cnt;
|
||||
|
||||
if (pdata->ets) {
|
||||
ets->cbs = pdata->ets->cbs;
|
||||
memcpy(ets->tc_tx_bw, pdata->ets->tc_tx_bw,
|
||||
sizeof(ets->tc_tx_bw));
|
||||
memcpy(ets->tc_tsa, pdata->ets->tc_tsa,
|
||||
sizeof(ets->tc_tsa));
|
||||
memcpy(ets->prio_tc, pdata->ets->prio_tc,
|
||||
sizeof(ets->prio_tc));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_dcb_ieee_setets(struct xgbe_prv_data *pdata,
|
||||
struct ieee_ets *ets)
|
||||
{
|
||||
unsigned int i, tc_ets, tc_ets_weight;
|
||||
u8 max_tc = 0;
|
||||
|
||||
tc_ets = 0;
|
||||
tc_ets_weight = 0;
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
axgbe_printf(1,
|
||||
"TC%u: tx_bw=%hhu, rx_bw=%hhu, tsa=%hhu\n", i,
|
||||
ets->tc_tx_bw[i], ets->tc_rx_bw[i],
|
||||
ets->tc_tsa[i]);
|
||||
axgbe_printf(1, "PRIO%u: TC=%hhu\n", i,
|
||||
ets->prio_tc[i]);
|
||||
|
||||
max_tc = max_t(u8, max_tc, ets->prio_tc[i]);
|
||||
if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]))
|
||||
max_tc = max_t(u8, max_tc, i);
|
||||
|
||||
switch (ets->tc_tsa[i]) {
|
||||
case IEEE_8021QAZ_TSA_STRICT:
|
||||
break;
|
||||
case IEEE_8021QAZ_TSA_ETS:
|
||||
tc_ets = 1;
|
||||
tc_ets_weight += ets->tc_tx_bw[i];
|
||||
break;
|
||||
default:
|
||||
axgbe_error(
|
||||
"unsupported TSA algorithm (%hhu)\n",
|
||||
ets->tc_tsa[i]);
|
||||
return (-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check maximum traffic class requested */
|
||||
if (max_tc >= pdata->hw_feat.tc_cnt) {
|
||||
axgbe_error(
|
||||
"exceeded number of supported traffic classes\n");
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
||||
/* Weights must add up to 100% */
|
||||
if (tc_ets && (tc_ets_weight != 100)) {
|
||||
axgbe_error(
|
||||
"sum of ETS algorithm weights is not 100 (%u)\n",
|
||||
tc_ets_weight);
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
||||
if (!pdata->ets) {
|
||||
pdata->ets = (struct ieee_ets *)malloc(sizeof(struct ieee_ets),
|
||||
M_AXGBE, M_NOWAIT); //TODO - when to free?
|
||||
|
||||
if (!pdata->ets)
|
||||
return (-ENOMEM);
|
||||
}
|
||||
|
||||
pdata->num_tcs = max_tc + 1;
|
||||
memcpy(pdata->ets, ets, sizeof(*pdata->ets));
|
||||
|
||||
pdata->hw_if.config_dcb_tc(pdata);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_dcb_ieee_getpfc(struct xgbe_prv_data *pdata,
|
||||
struct ieee_pfc *pfc)
|
||||
{
|
||||
|
||||
/* Set number of supported PFC traffic classes */
|
||||
pfc->pfc_cap = pdata->hw_feat.tc_cnt;
|
||||
|
||||
if (pdata->pfc) {
|
||||
pfc->pfc_en = pdata->pfc->pfc_en;
|
||||
pfc->mbc = pdata->pfc->mbc;
|
||||
pfc->delay = pdata->pfc->delay;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_dcb_ieee_setpfc(struct xgbe_prv_data *pdata,
|
||||
struct ieee_pfc *pfc)
|
||||
{
|
||||
|
||||
axgbe_printf(1,
|
||||
"cap=%hhu, en=%#hhx, mbc=%hhu, delay=%d\n",
|
||||
pfc->pfc_cap, pfc->pfc_en, pfc->mbc, pfc->delay);
|
||||
|
||||
/* Check PFC for supported number of traffic classes */
|
||||
if (pfc->pfc_en & ~((1 << pdata->hw_feat.tc_cnt) - 1)) {
|
||||
axgbe_error(
|
||||
"PFC requested for unsupported traffic class\n");
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
||||
if (!pdata->pfc) {
|
||||
pdata->pfc = (struct ieee_pfc *)malloc(sizeof(struct ieee_pfc),
|
||||
M_AXGBE, M_NOWAIT); //TODO - when to free?
|
||||
|
||||
if (!pdata->pfc)
|
||||
return (-ENOMEM);
|
||||
}
|
||||
|
||||
memcpy(pdata->pfc, pfc, sizeof(*pdata->pfc));
|
||||
|
||||
pdata->hw_if.config_dcb_pfc(pdata);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static u8 xgbe_dcb_getdcbx(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
return (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE);
|
||||
}
|
||||
|
||||
static u8 xgbe_dcb_setdcbx(struct xgbe_prv_data *pdata, u8 dcbx)
|
||||
{
|
||||
u8 support = xgbe_dcb_getdcbx(pdata);
|
||||
|
||||
axgbe_printf(1, "DCBX=%#hhx\n", dcbx);
|
||||
|
||||
if (dcbx & ~support)
|
||||
return (1);
|
||||
|
||||
if ((dcbx & support) != support)
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* AMD 10Gb Ethernet driver
|
||||
*
|
||||
* Copyright (c) 2014-2016,2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is available to you under your choice of the following two
|
||||
* licenses:
|
||||
*
|
||||
* License 1: GPLv2
|
||||
*
|
||||
* Copyright (c) 2014 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is free software; you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or (at
|
||||
@ -56,9 +56,6 @@
|
||||
*
|
||||
* License 2: Modified BSD
|
||||
*
|
||||
* Copyright (c) 2014 Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
@ -120,221 +117,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include "xgbe.h"
|
||||
#include "xgbe-common.h"
|
||||
|
||||
static void xgbe_unmap_rdata(struct xgbe_prv_data *, struct xgbe_ring_data *);
|
||||
|
||||
static void xgbe_free_ring(struct xgbe_prv_data *pdata,
|
||||
struct xgbe_ring *ring)
|
||||
{
|
||||
struct xgbe_ring_data *rdata;
|
||||
unsigned int i;
|
||||
|
||||
if (!ring)
|
||||
return;
|
||||
|
||||
bus_dmamap_destroy(ring->mbuf_dmat, ring->mbuf_map);
|
||||
bus_dma_tag_destroy(ring->mbuf_dmat);
|
||||
|
||||
ring->mbuf_map = NULL;
|
||||
ring->mbuf_dmat = NULL;
|
||||
|
||||
if (ring->rdata) {
|
||||
for (i = 0; i < ring->rdesc_count; i++) {
|
||||
rdata = XGBE_GET_DESC_DATA(ring, i);
|
||||
xgbe_unmap_rdata(pdata, rdata);
|
||||
}
|
||||
|
||||
free(ring->rdata, M_AXGBE);
|
||||
ring->rdata = NULL;
|
||||
}
|
||||
|
||||
bus_dmamap_unload(ring->rdesc_dmat, ring->rdesc_map);
|
||||
bus_dmamem_free(ring->rdesc_dmat, ring->rdesc, ring->rdesc_map);
|
||||
bus_dma_tag_destroy(ring->rdesc_dmat);
|
||||
|
||||
ring->rdesc_map = NULL;
|
||||
ring->rdesc_dmat = NULL;
|
||||
ring->rdesc = NULL;
|
||||
}
|
||||
|
||||
static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_channel *channel;
|
||||
unsigned int i;
|
||||
|
||||
DBGPR("-->xgbe_free_ring_resources\n");
|
||||
|
||||
channel = pdata->channel;
|
||||
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||
xgbe_free_ring(pdata, channel->tx_ring);
|
||||
xgbe_free_ring(pdata, channel->rx_ring);
|
||||
}
|
||||
|
||||
DBGPR("<--xgbe_free_ring_resources\n");
|
||||
}
|
||||
|
||||
static void xgbe_ring_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg,
|
||||
int error)
|
||||
{
|
||||
if (error)
|
||||
return;
|
||||
*(bus_addr_t *) arg = segs->ds_addr;
|
||||
}
|
||||
|
||||
static int xgbe_init_ring(struct xgbe_prv_data *pdata,
|
||||
struct xgbe_ring *ring, unsigned int rdesc_count)
|
||||
{
|
||||
bus_size_t len;
|
||||
int err, flags;
|
||||
|
||||
DBGPR("-->xgbe_init_ring\n");
|
||||
|
||||
if (!ring)
|
||||
return 0;
|
||||
|
||||
flags = 0;
|
||||
if (pdata->coherent)
|
||||
flags = BUS_DMA_COHERENT;
|
||||
|
||||
/* Descriptors */
|
||||
ring->rdesc_count = rdesc_count;
|
||||
len = sizeof(struct xgbe_ring_desc) * rdesc_count;
|
||||
err = bus_dma_tag_create(pdata->dmat, 512, 0, BUS_SPACE_MAXADDR,
|
||||
BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, flags, NULL, NULL,
|
||||
&ring->rdesc_dmat);
|
||||
if (err != 0) {
|
||||
printf("Unable to create the DMA tag: %d\n", err);
|
||||
return -err;
|
||||
}
|
||||
|
||||
err = bus_dmamem_alloc(ring->rdesc_dmat, (void **)&ring->rdesc,
|
||||
BUS_DMA_WAITOK | BUS_DMA_COHERENT, &ring->rdesc_map);
|
||||
if (err != 0) {
|
||||
bus_dma_tag_destroy(ring->rdesc_dmat);
|
||||
printf("Unable to allocate DMA memory: %d\n", err);
|
||||
return -err;
|
||||
}
|
||||
err = bus_dmamap_load(ring->rdesc_dmat, ring->rdesc_map, ring->rdesc,
|
||||
len, xgbe_ring_dmamap_cb, &ring->rdesc_paddr, 0);
|
||||
if (err != 0) {
|
||||
bus_dmamem_free(ring->rdesc_dmat, ring->rdesc, ring->rdesc_map);
|
||||
bus_dma_tag_destroy(ring->rdesc_dmat);
|
||||
printf("Unable to load DMA memory\n");
|
||||
return -err;
|
||||
}
|
||||
|
||||
/* Descriptor information */
|
||||
ring->rdata = malloc(rdesc_count * sizeof(struct xgbe_ring_data),
|
||||
M_AXGBE, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Create the space DMA tag for mbufs */
|
||||
err = bus_dma_tag_create(pdata->dmat, 1, 0, BUS_SPACE_MAXADDR,
|
||||
BUS_SPACE_MAXADDR, NULL, NULL, XGBE_TX_MAX_BUF_SIZE * rdesc_count,
|
||||
rdesc_count, XGBE_TX_MAX_BUF_SIZE, flags, NULL, NULL,
|
||||
&ring->mbuf_dmat);
|
||||
if (err != 0)
|
||||
return -err;
|
||||
|
||||
err = bus_dmamap_create(ring->mbuf_dmat, 0, &ring->mbuf_map);
|
||||
if (err != 0)
|
||||
return -err;
|
||||
|
||||
DBGPR("<--xgbe_init_ring\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_channel *channel;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
DBGPR("-->xgbe_alloc_ring_resources\n");
|
||||
|
||||
channel = pdata->channel;
|
||||
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||
ret = xgbe_init_ring(pdata, channel->tx_ring,
|
||||
pdata->tx_desc_count);
|
||||
if (ret) {
|
||||
printf("error initializing Tx ring\n");
|
||||
goto err_ring;
|
||||
}
|
||||
|
||||
ret = xgbe_init_ring(pdata, channel->rx_ring,
|
||||
pdata->rx_desc_count);
|
||||
if (ret) {
|
||||
printf("error initializing Rx ring\n");
|
||||
goto err_ring;
|
||||
}
|
||||
}
|
||||
|
||||
DBGPR("<--xgbe_alloc_ring_resources\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_ring:
|
||||
xgbe_free_ring_resources(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
|
||||
struct xgbe_ring *ring,
|
||||
struct xgbe_ring_data *rdata)
|
||||
{
|
||||
bus_dmamap_t mbuf_map;
|
||||
bus_dma_segment_t segs[2];
|
||||
struct mbuf *m0, *m1;
|
||||
int err, nsegs;
|
||||
|
||||
m0 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MCLBYTES);
|
||||
if (m0 == NULL)
|
||||
return (-ENOBUFS);
|
||||
|
||||
m1 = m_getjcl(M_NOWAIT, MT_DATA, 0, MCLBYTES);
|
||||
if (m1 == NULL) {
|
||||
m_freem(m0);
|
||||
return (-ENOBUFS);
|
||||
}
|
||||
|
||||
m0->m_next = m1;
|
||||
m0->m_flags |= M_PKTHDR;
|
||||
m0->m_len = MHLEN;
|
||||
m0->m_pkthdr.len = MHLEN + MCLBYTES;
|
||||
|
||||
m1->m_len = MCLBYTES;
|
||||
m1->m_next = NULL;
|
||||
m1->m_pkthdr.len = MCLBYTES;
|
||||
|
||||
err = bus_dmamap_create(ring->mbuf_dmat, 0, &mbuf_map);
|
||||
if (err != 0) {
|
||||
m_freem(m0);
|
||||
return (-err);
|
||||
}
|
||||
|
||||
err = bus_dmamap_load_mbuf_sg(ring->mbuf_dmat, mbuf_map, m0, segs,
|
||||
&nsegs, BUS_DMA_NOWAIT);
|
||||
if (err != 0) {
|
||||
m_freem(m0);
|
||||
bus_dmamap_destroy(ring->mbuf_dmat, mbuf_map);
|
||||
return (-err);
|
||||
}
|
||||
|
||||
KASSERT(nsegs == 2,
|
||||
("xgbe_map_rx_buffer: Unable to handle multiple segments %d",
|
||||
nsegs));
|
||||
|
||||
rdata->mb = m0;
|
||||
rdata->mbuf_free = 0;
|
||||
rdata->mbuf_dmat = ring->mbuf_dmat;
|
||||
rdata->mbuf_map = mbuf_map;
|
||||
rdata->mbuf_hdr_paddr = segs[0].ds_addr;
|
||||
rdata->mbuf_data_paddr = segs[1].ds_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
static void
|
||||
xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
struct xgbe_channel *channel;
|
||||
@ -346,8 +130,10 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
|
||||
DBGPR("-->xgbe_wrapper_tx_descriptor_init\n");
|
||||
|
||||
channel = pdata->channel;
|
||||
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||
for (i = 0; i < pdata->channel_count; i++) {
|
||||
|
||||
channel = pdata->channel[i];
|
||||
|
||||
ring = channel->tx_ring;
|
||||
if (!ring)
|
||||
break;
|
||||
@ -375,7 +161,8 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
DBGPR("<--xgbe_wrapper_tx_descriptor_init\n");
|
||||
}
|
||||
|
||||
static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
static void
|
||||
xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
struct xgbe_channel *channel;
|
||||
@ -387,8 +174,10 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
|
||||
DBGPR("-->xgbe_wrapper_rx_descriptor_init\n");
|
||||
|
||||
channel = pdata->channel;
|
||||
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||
for (i = 0; i < pdata->channel_count; i++) {
|
||||
|
||||
channel = pdata->channel[i];
|
||||
|
||||
ring = channel->rx_ring;
|
||||
if (!ring)
|
||||
break;
|
||||
@ -402,9 +191,6 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
rdata->rdesc = rdesc;
|
||||
rdata->rdata_paddr = rdesc_paddr;
|
||||
|
||||
if (xgbe_map_rx_buffer(pdata, ring, rdata))
|
||||
break;
|
||||
|
||||
rdesc++;
|
||||
rdesc_paddr += sizeof(struct xgbe_ring_desc);
|
||||
}
|
||||
@ -416,124 +202,10 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
|
||||
}
|
||||
}
|
||||
|
||||
static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata,
|
||||
struct xgbe_ring_data *rdata)
|
||||
void
|
||||
xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if)
|
||||
{
|
||||
|
||||
if (rdata->mbuf_map != NULL)
|
||||
bus_dmamap_destroy(rdata->mbuf_dmat, rdata->mbuf_map);
|
||||
|
||||
if (rdata->mbuf_free)
|
||||
m_freem(rdata->mb);
|
||||
|
||||
rdata->mb = NULL;
|
||||
rdata->mbuf_free = 0;
|
||||
rdata->mbuf_hdr_paddr = 0;
|
||||
rdata->mbuf_data_paddr = 0;
|
||||
rdata->mbuf_len = 0;
|
||||
|
||||
memset(&rdata->tx, 0, sizeof(rdata->tx));
|
||||
memset(&rdata->rx, 0, sizeof(rdata->rx));
|
||||
}
|
||||
|
||||
struct xgbe_map_tx_skb_data {
|
||||
struct xgbe_ring *ring;
|
||||
struct xgbe_packet_data *packet;
|
||||
unsigned int cur_index;
|
||||
};
|
||||
|
||||
static void xgbe_map_tx_skb_cb(void *callback_arg, bus_dma_segment_t *segs,
|
||||
int nseg, bus_size_t mapsize, int error)
|
||||
{
|
||||
struct xgbe_map_tx_skb_data *data;
|
||||
struct xgbe_ring_data *rdata;
|
||||
struct xgbe_ring *ring;
|
||||
int i;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
data = callback_arg;
|
||||
ring = data->ring;
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
rdata = XGBE_GET_DESC_DATA(ring, data->cur_index);
|
||||
|
||||
KASSERT(segs[i].ds_len <= XGBE_TX_MAX_BUF_SIZE,
|
||||
("%s: Segment size is too large %ld > %d", __func__,
|
||||
segs[i].ds_len, XGBE_TX_MAX_BUF_SIZE));
|
||||
|
||||
if (i == 0) {
|
||||
rdata->mbuf_dmat = ring->mbuf_dmat;
|
||||
bus_dmamap_create(ring->mbuf_dmat, 0, &ring->mbuf_map);
|
||||
}
|
||||
|
||||
rdata->mbuf_hdr_paddr = 0;
|
||||
rdata->mbuf_data_paddr = segs[i].ds_addr;
|
||||
rdata->mbuf_len = segs[i].ds_len;
|
||||
|
||||
data->packet->length += rdata->mbuf_len;
|
||||
|
||||
data->cur_index++;
|
||||
}
|
||||
}
|
||||
|
||||
static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct mbuf *m)
|
||||
{
|
||||
struct xgbe_ring *ring = channel->tx_ring;
|
||||
struct xgbe_map_tx_skb_data cbdata;
|
||||
struct xgbe_ring_data *rdata;
|
||||
struct xgbe_packet_data *packet;
|
||||
unsigned int start_index, cur_index;
|
||||
int err;
|
||||
|
||||
DBGPR("-->xgbe_map_tx_skb: cur = %d\n", ring->cur);
|
||||
|
||||
start_index = ring->cur;
|
||||
cur_index = ring->cur;
|
||||
|
||||
packet = &ring->packet_data;
|
||||
packet->rdesc_count = 0;
|
||||
packet->length = 0;
|
||||
|
||||
cbdata.ring = ring;
|
||||
cbdata.packet = packet;
|
||||
cbdata.cur_index = cur_index;
|
||||
|
||||
err = bus_dmamap_load_mbuf(ring->mbuf_dmat, ring->mbuf_map, m,
|
||||
xgbe_map_tx_skb_cb, &cbdata, BUS_DMA_NOWAIT);
|
||||
if (err != 0) /* TODO: Undo the mapping */
|
||||
return (-err);
|
||||
|
||||
cur_index = cbdata.cur_index;
|
||||
|
||||
/* Save the mbuf address in the last entry. We always have some data
|
||||
* that has been mapped so rdata is always advanced past the last
|
||||
* piece of mapped data - use the entry pointed to by cur_index - 1.
|
||||
*/
|
||||
rdata = XGBE_GET_DESC_DATA(ring, cur_index - 1);
|
||||
rdata->mb = m;
|
||||
rdata->mbuf_free = 1;
|
||||
|
||||
/* Save the number of descriptor entries used */
|
||||
packet->rdesc_count = cur_index - start_index;
|
||||
|
||||
DBGPR("<--xgbe_map_tx_skb: count=%u\n", packet->rdesc_count);
|
||||
|
||||
return packet->rdesc_count;
|
||||
}
|
||||
|
||||
void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if)
|
||||
{
|
||||
DBGPR("-->xgbe_init_function_ptrs_desc\n");
|
||||
|
||||
desc_if->alloc_ring_resources = xgbe_alloc_ring_resources;
|
||||
desc_if->free_ring_resources = xgbe_free_ring_resources;
|
||||
desc_if->map_tx_skb = xgbe_map_tx_skb;
|
||||
desc_if->map_rx_buffer = xgbe_map_rx_buffer;
|
||||
desc_if->unmap_rdata = xgbe_unmap_rdata;
|
||||
desc_if->wrapper_tx_desc_init = xgbe_wrapper_tx_descriptor_init;
|
||||
desc_if->wrapper_rx_desc_init = xgbe_wrapper_rx_descriptor_init;
|
||||
|
||||
DBGPR("<--xgbe_init_function_ptrs_desc\n");
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
532
sys/dev/axgbe/xgbe-i2c.c
Normal file
532
sys/dev/axgbe/xgbe-i2c.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*
|
||||
* AMD 10Gb Ethernet driver
|
||||
*
|
||||
* Copyright (c) 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is available to you under your choice of the following two
|
||||
* licenses:
|
||||
*
|
||||
* License 1: GPLv2
|
||||
*
|
||||
* This file is free software; you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* License 2: Modified BSD
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Advanced Micro Devices, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "xgbe.h"
|
||||
#include "xgbe-common.h"
|
||||
|
||||
#define XGBE_ABORT_COUNT 500
|
||||
#define XGBE_DISABLE_COUNT 1000
|
||||
|
||||
#define XGBE_STD_SPEED 1
|
||||
|
||||
#define XGBE_INTR_RX_FULL BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX)
|
||||
#define XGBE_INTR_TX_EMPTY BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX)
|
||||
#define XGBE_INTR_TX_ABRT BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX)
|
||||
#define XGBE_INTR_STOP_DET BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX)
|
||||
#define XGBE_DEFAULT_INT_MASK (XGBE_INTR_RX_FULL | \
|
||||
XGBE_INTR_TX_EMPTY | \
|
||||
XGBE_INTR_TX_ABRT | \
|
||||
XGBE_INTR_STOP_DET)
|
||||
|
||||
#define XGBE_I2C_READ BIT(8)
|
||||
#define XGBE_I2C_STOP BIT(9)
|
||||
|
||||
static int
|
||||
xgbe_i2c_abort(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int wait = XGBE_ABORT_COUNT;
|
||||
|
||||
/* Must be enabled to recognize the abort request */
|
||||
XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1);
|
||||
|
||||
/* Issue the abort */
|
||||
XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1);
|
||||
|
||||
while (wait--) {
|
||||
if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT))
|
||||
return (0);
|
||||
|
||||
DELAY(500);
|
||||
}
|
||||
|
||||
return (-EBUSY);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_i2c_set_enable(struct xgbe_prv_data *pdata, bool enable)
|
||||
{
|
||||
unsigned int wait = XGBE_DISABLE_COUNT;
|
||||
unsigned int mode = enable ? 1 : 0;
|
||||
|
||||
while (wait--) {
|
||||
XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode);
|
||||
if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode)
|
||||
return (0);
|
||||
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
return (-EBUSY);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_i2c_disable(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
ret = xgbe_i2c_set_enable(pdata, false);
|
||||
if (ret) {
|
||||
/* Disable failed, try an abort */
|
||||
ret = xgbe_i2c_abort(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("%s: i2c_abort %d\n", __func__, ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Abort succeeded, try to disable again */
|
||||
ret = xgbe_i2c_set_enable(pdata, false);
|
||||
}
|
||||
|
||||
axgbe_printf(3, "%s: final i2c_disable %d\n", __func__, ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_i2c_enable(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
return (xgbe_i2c_set_enable(pdata, true));
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_clear_all_interrupts(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
XI2C_IOREAD(pdata, IC_CLR_INTR);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_disable_interrupts(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
XI2C_IOWRITE(pdata, IC_INTR_MASK, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_enable_interrupts(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
XI2C_IOWRITE(pdata, IC_INTR_MASK, XGBE_DEFAULT_INT_MASK);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_write(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
|
||||
unsigned int tx_slots, cmd;
|
||||
|
||||
/* Configured to never receive Rx overflows, so fill up Tx fifo */
|
||||
tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR);
|
||||
axgbe_printf(3, "%s: tx_slots %d tx_len %d\n", __func__, tx_slots,
|
||||
state->tx_len);
|
||||
|
||||
while (tx_slots && state->tx_len) {
|
||||
if (state->op->cmd == XGBE_I2C_CMD_READ)
|
||||
cmd = XGBE_I2C_READ;
|
||||
else
|
||||
cmd = *state->tx_buf++;
|
||||
|
||||
axgbe_printf(3, "%s: cmd %d tx_len %d\n", __func__, cmd,
|
||||
state->tx_len);
|
||||
|
||||
if (state->tx_len == 1)
|
||||
XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1);
|
||||
|
||||
XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd);
|
||||
|
||||
tx_slots--;
|
||||
state->tx_len--;
|
||||
}
|
||||
|
||||
/* No more Tx operations, so ignore TX_EMPTY and return */
|
||||
if (!state->tx_len)
|
||||
XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_read(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
|
||||
unsigned int rx_slots;
|
||||
|
||||
/* Anything to be read? */
|
||||
axgbe_printf(3, "%s: op cmd %d\n", __func__, state->op->cmd);
|
||||
if (state->op->cmd != XGBE_I2C_CMD_READ)
|
||||
return;
|
||||
|
||||
rx_slots = XI2C_IOREAD(pdata, IC_RXFLR);
|
||||
axgbe_printf(3, "%s: rx_slots %d rx_len %d\n", __func__, rx_slots,
|
||||
state->rx_len);
|
||||
|
||||
while (rx_slots && state->rx_len) {
|
||||
*state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD);
|
||||
state->rx_len--;
|
||||
rx_slots--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata, unsigned int isr)
|
||||
{
|
||||
struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
|
||||
|
||||
if (isr & XGBE_INTR_TX_ABRT) {
|
||||
state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE);
|
||||
XI2C_IOREAD(pdata, IC_CLR_TX_ABRT);
|
||||
}
|
||||
|
||||
if (isr & XGBE_INTR_STOP_DET)
|
||||
XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_isr(void *data)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
|
||||
struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
|
||||
unsigned int isr;
|
||||
|
||||
isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT);
|
||||
axgbe_printf(3, "%s: isr 0x%x\n", __func__, isr);
|
||||
if (!isr)
|
||||
goto reissue_check;
|
||||
|
||||
axgbe_printf(3, "%s: I2C interrupt status=%#010x\n", __func__, isr);
|
||||
|
||||
xgbe_i2c_clear_isr_interrupts(pdata, isr);
|
||||
|
||||
if (isr & XGBE_INTR_TX_ABRT) {
|
||||
axgbe_printf(1, "%s: I2C TX_ABRT received (%#010x) for target "
|
||||
"%#04x\n", __func__, state->tx_abort_source,
|
||||
state->op->target);
|
||||
|
||||
xgbe_i2c_disable_interrupts(pdata);
|
||||
|
||||
state->ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for data in the Rx fifo */
|
||||
xgbe_i2c_read(pdata);
|
||||
|
||||
/* Fill up the Tx fifo next */
|
||||
xgbe_i2c_write(pdata);
|
||||
|
||||
out:
|
||||
/* Complete on an error or STOP condition */
|
||||
axgbe_printf(3, "%s: ret %d stop %d\n", __func__, state->ret,
|
||||
XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET));
|
||||
|
||||
if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET))
|
||||
pdata->i2c_complete = true;
|
||||
|
||||
return;
|
||||
|
||||
reissue_check:
|
||||
/* Reissue interrupt if status is not clear */
|
||||
if (pdata->vdata->irq_reissue_support)
|
||||
XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 2);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_set_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = XI2C_IOREAD(pdata, IC_CON);
|
||||
XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1);
|
||||
XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1);
|
||||
XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1);
|
||||
XI2C_SET_BITS(reg, IC_CON, SPEED, XGBE_STD_SPEED);
|
||||
XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1);
|
||||
XI2C_IOWRITE(pdata, IC_CON, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_get_features(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_i2c *i2c = &pdata->i2c;
|
||||
unsigned int reg;
|
||||
|
||||
reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1);
|
||||
i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
|
||||
MAX_SPEED_MODE);
|
||||
i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
|
||||
RX_BUFFER_DEPTH);
|
||||
i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
|
||||
TX_BUFFER_DEPTH);
|
||||
|
||||
axgbe_printf(3, "%s: I2C features: %s=%u, %s=%u, %s=%u\n", __func__,
|
||||
"MAX_SPEED_MODE", i2c->max_speed_mode,
|
||||
"RX_BUFFER_DEPTH", i2c->rx_fifo_size,
|
||||
"TX_BUFFER_DEPTH", i2c->tx_fifo_size);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr)
|
||||
{
|
||||
XI2C_IOWRITE(pdata, IC_TAR, addr);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
xgbe_i2c_isr(pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op)
|
||||
{
|
||||
struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
|
||||
unsigned long timeout;
|
||||
int ret;
|
||||
|
||||
mtx_lock(&pdata->i2c_mutex);
|
||||
|
||||
axgbe_printf(3, "i2c xfer started ---->>>\n");
|
||||
|
||||
ret = xgbe_i2c_disable(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("failed to disable i2c master\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
xgbe_i2c_set_target(pdata, op->target);
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->op = op;
|
||||
state->tx_len = op->len;
|
||||
state->tx_buf = op->buf;
|
||||
state->rx_len = op->len;
|
||||
state->rx_buf = op->buf;
|
||||
|
||||
xgbe_i2c_clear_all_interrupts(pdata);
|
||||
ret = xgbe_i2c_enable(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("failed to enable i2c master\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Enabling the interrupts will cause the TX FIFO empty interrupt to
|
||||
* fire and begin to process the command via the ISR.
|
||||
*/
|
||||
xgbe_i2c_enable_interrupts(pdata);
|
||||
|
||||
timeout = ticks + (20 * hz);
|
||||
while (ticks < timeout) {
|
||||
|
||||
if (!pdata->i2c_complete) {
|
||||
DELAY(200);
|
||||
continue;
|
||||
}
|
||||
|
||||
axgbe_printf(1, "%s: I2C OP complete\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ticks >= timeout) && !pdata->i2c_complete) {
|
||||
axgbe_error("%s: operation timed out\n", __func__);
|
||||
ret = -ETIMEDOUT;
|
||||
goto disable;
|
||||
}
|
||||
|
||||
ret = state->ret;
|
||||
axgbe_printf(3, "%s: i2c xfer ret %d abrt_source 0x%x \n", __func__,
|
||||
ret, state->tx_abort_source);
|
||||
if (ret) {
|
||||
|
||||
axgbe_error("%s: i2c xfer ret %d abrt_source 0x%x \n", __func__,
|
||||
ret, state->tx_abort_source);
|
||||
if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK)
|
||||
ret = -ENOTCONN;
|
||||
else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST)
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
axgbe_printf(3, "i2c xfer finished ---->>>\n");
|
||||
|
||||
disable:
|
||||
pdata->i2c_complete = false;
|
||||
xgbe_i2c_disable_interrupts(pdata);
|
||||
xgbe_i2c_disable(pdata);
|
||||
|
||||
out:
|
||||
mtx_unlock(&pdata->i2c_mutex);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_i2c_stop(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
if (!pdata->i2c.started)
|
||||
return;
|
||||
|
||||
axgbe_printf(3, "stopping I2C\n");
|
||||
|
||||
pdata->i2c.started = 0;
|
||||
|
||||
xgbe_i2c_disable_interrupts(pdata);
|
||||
xgbe_i2c_disable(pdata);
|
||||
xgbe_i2c_clear_all_interrupts(pdata);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_i2c_start(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
if (pdata->i2c.started)
|
||||
return (0);
|
||||
|
||||
pdata->i2c.started = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_i2c_init(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* initialize lock for i2c */
|
||||
mtx_init(&pdata->i2c_mutex, "xgbe i2c mutex lock", NULL, MTX_DEF);
|
||||
pdata->i2c_complete = false;
|
||||
|
||||
xgbe_i2c_disable_interrupts(pdata);
|
||||
|
||||
ret = xgbe_i2c_disable(pdata);
|
||||
if (ret) {
|
||||
axgbe_error("failed to disable i2c master\n");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
xgbe_i2c_get_features(pdata);
|
||||
|
||||
xgbe_i2c_set_mode(pdata);
|
||||
|
||||
xgbe_i2c_clear_all_interrupts(pdata);
|
||||
|
||||
xgbe_dump_i2c_registers(pdata);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *i2c_if)
|
||||
{
|
||||
i2c_if->i2c_init = xgbe_i2c_init;
|
||||
|
||||
i2c_if->i2c_start = xgbe_i2c_start;
|
||||
i2c_if->i2c_stop = xgbe_i2c_stop;
|
||||
|
||||
i2c_if->i2c_xfer = xgbe_i2c_xfer;
|
||||
|
||||
i2c_if->i2c_isr = xgbe_i2c_combined_isr;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
707
sys/dev/axgbe/xgbe-phy-v1.c
Normal file
707
sys/dev/axgbe/xgbe-phy-v1.c
Normal file
@ -0,0 +1,707 @@
|
||||
/*
|
||||
* AMD 10Gb Ethernet driver
|
||||
*
|
||||
* Copyright (c) 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is available to you under your choice of the following two
|
||||
* licenses:
|
||||
*
|
||||
* License 1: GPLv2
|
||||
*
|
||||
* This file is free software; you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* License 2: Modified BSD
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Advanced Micro Devices, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "xgbe.h"
|
||||
#include "xgbe-common.h"
|
||||
|
||||
struct xgbe_phy_data {
|
||||
/* 1000/10000 vs 2500/10000 indicator */
|
||||
unsigned int speed_set;
|
||||
|
||||
/* SerDes UEFI configurable settings.
|
||||
* Switching between modes/speeds requires new values for some
|
||||
* SerDes settings. The values can be supplied as device
|
||||
* properties in array format. The first array entry is for
|
||||
* 1GbE, second for 2.5GbE and third for 10GbE
|
||||
*/
|
||||
uint32_t blwc[XGBE_SPEEDS];
|
||||
uint32_t cdr_rate[XGBE_SPEEDS];
|
||||
uint32_t pq_skew[XGBE_SPEEDS];
|
||||
uint32_t tx_amp[XGBE_SPEEDS];
|
||||
uint32_t dfe_tap_cfg[XGBE_SPEEDS];
|
||||
uint32_t dfe_tap_ena[XGBE_SPEEDS];
|
||||
};
|
||||
|
||||
static void
|
||||
xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
|
||||
}
|
||||
|
||||
static enum xgbe_mode
|
||||
xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
enum xgbe_mode mode;
|
||||
unsigned int ad_reg, lp_reg;
|
||||
|
||||
XGBE_SET_LP_ADV(&pdata->phy, Autoneg);
|
||||
XGBE_SET_LP_ADV(&pdata->phy, Backplane);
|
||||
|
||||
/* Compare Advertisement and Link Partner register 1 */
|
||||
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
|
||||
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
|
||||
if (lp_reg & 0x400)
|
||||
XGBE_SET_LP_ADV(&pdata->phy, Pause);
|
||||
if (lp_reg & 0x800)
|
||||
XGBE_SET_LP_ADV(&pdata->phy, Asym_Pause);
|
||||
|
||||
axgbe_printf(1, "%s: pause_autoneg %d ad_reg 0x%x lp_reg 0x%x\n",
|
||||
__func__, pdata->phy.pause_autoneg, ad_reg, lp_reg);
|
||||
|
||||
if (pdata->phy.pause_autoneg) {
|
||||
/* Set flow control based on auto-negotiation result */
|
||||
pdata->phy.tx_pause = 0;
|
||||
pdata->phy.rx_pause = 0;
|
||||
|
||||
if (ad_reg & lp_reg & 0x400) {
|
||||
pdata->phy.tx_pause = 1;
|
||||
pdata->phy.rx_pause = 1;
|
||||
} else if (ad_reg & lp_reg & 0x800) {
|
||||
if (ad_reg & 0x400)
|
||||
pdata->phy.rx_pause = 1;
|
||||
else if (lp_reg & 0x400)
|
||||
pdata->phy.tx_pause = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare Advertisement and Link Partner register 2 */
|
||||
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
|
||||
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
|
||||
if (lp_reg & 0x80)
|
||||
XGBE_SET_LP_ADV(&pdata->phy, 10000baseKR_Full);
|
||||
if (lp_reg & 0x20) {
|
||||
if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
|
||||
XGBE_SET_LP_ADV(&pdata->phy, 2500baseX_Full);
|
||||
else
|
||||
XGBE_SET_LP_ADV(&pdata->phy, 1000baseKX_Full);
|
||||
}
|
||||
|
||||
ad_reg &= lp_reg;
|
||||
if (ad_reg & 0x80) {
|
||||
pdata->phy.speed = SPEED_10000;
|
||||
mode = XGBE_MODE_KR;
|
||||
} else if (ad_reg & 0x20) {
|
||||
switch (pdata->speed_set) {
|
||||
case XGBE_SPEEDSET_1000_10000:
|
||||
pdata->phy.speed = SPEED_1000;
|
||||
mode = XGBE_MODE_KX_1000;
|
||||
break;
|
||||
|
||||
case XGBE_SPEEDSET_2500_10000:
|
||||
pdata->phy.speed = SPEED_2500;
|
||||
mode = XGBE_MODE_KX_2500;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mode = XGBE_MODE_UNKNOWN;
|
||||
pdata->phy.speed = SPEED_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Compare Advertisement and Link Partner register 3 */
|
||||
ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
|
||||
lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
|
||||
if (lp_reg & 0xc000)
|
||||
XGBE_SET_LP_ADV(&pdata->phy, 10000baseR_FEC);
|
||||
|
||||
return (mode);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, struct xgbe_phy *dphy)
|
||||
{
|
||||
XGBE_LM_COPY(dphy, advertising, &pdata->phy, advertising);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_an_config(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
/* Nothing uniquely required for an configuration */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static enum xgbe_an_mode
|
||||
xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
return (XGBE_AN_MODE_CL73);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
|
||||
reg |= MDIO_CTRL1_LPOWER;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
|
||||
|
||||
DELAY(75);
|
||||
|
||||
reg &= ~MDIO_CTRL1_LPOWER;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
/* Assert Rx and Tx ratechange */
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int wait;
|
||||
uint16_t status;
|
||||
|
||||
/* Release Rx and Tx ratechange */
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
|
||||
|
||||
/* Wait for Rx and Tx ready */
|
||||
wait = XGBE_RATECHANGE_COUNT;
|
||||
while (wait--) {
|
||||
DELAY(50);
|
||||
|
||||
status = XSIR0_IOREAD(pdata, SIR0_STATUS);
|
||||
if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
|
||||
XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
|
||||
goto rx_reset;
|
||||
}
|
||||
|
||||
axgbe_printf(2, "SerDes rx/tx not ready (%#hx)\n", status);
|
||||
|
||||
rx_reset:
|
||||
/* Perform Rx reset for the DFE changes */
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
unsigned int reg;
|
||||
|
||||
/* Set PCS to KR/10G speed */
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
|
||||
reg &= ~MDIO_PCS_CTRL2_TYPE;
|
||||
reg |= MDIO_PCS_CTRL2_10GBR;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
|
||||
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
reg &= ~MDIO_CTRL1_SPEEDSEL;
|
||||
reg |= MDIO_CTRL1_SPEED10G;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
|
||||
|
||||
xgbe_phy_pcs_power_cycle(pdata);
|
||||
|
||||
/* Set SerDes to 10G speed */
|
||||
xgbe_phy_start_ratechange(pdata);
|
||||
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
|
||||
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
|
||||
phy_data->cdr_rate[XGBE_SPEED_10000]);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
|
||||
phy_data->tx_amp[XGBE_SPEED_10000]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
|
||||
phy_data->blwc[XGBE_SPEED_10000]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
|
||||
phy_data->pq_skew[XGBE_SPEED_10000]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
|
||||
phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
|
||||
XRXTX_IOWRITE(pdata, RXTX_REG22,
|
||||
phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
|
||||
|
||||
xgbe_phy_complete_ratechange(pdata);
|
||||
|
||||
axgbe_printf(2, "10GbE KR mode set\n");
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
unsigned int reg;
|
||||
|
||||
/* Set PCS to KX/1G speed */
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
|
||||
reg &= ~MDIO_PCS_CTRL2_TYPE;
|
||||
reg |= MDIO_PCS_CTRL2_10GBX;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
|
||||
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
reg &= ~MDIO_CTRL1_SPEEDSEL;
|
||||
reg |= MDIO_CTRL1_SPEED1G;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
|
||||
|
||||
xgbe_phy_pcs_power_cycle(pdata);
|
||||
|
||||
/* Set SerDes to 2.5G speed */
|
||||
xgbe_phy_start_ratechange(pdata);
|
||||
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
|
||||
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
|
||||
phy_data->cdr_rate[XGBE_SPEED_2500]);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
|
||||
phy_data->tx_amp[XGBE_SPEED_2500]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
|
||||
phy_data->blwc[XGBE_SPEED_2500]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
|
||||
phy_data->pq_skew[XGBE_SPEED_2500]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
|
||||
phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
|
||||
XRXTX_IOWRITE(pdata, RXTX_REG22,
|
||||
phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
|
||||
|
||||
xgbe_phy_complete_ratechange(pdata);
|
||||
|
||||
axgbe_printf(2, "2.5GbE KX mode set\n");
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
unsigned int reg;
|
||||
|
||||
/* Set PCS to KX/1G speed */
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
|
||||
reg &= ~MDIO_PCS_CTRL2_TYPE;
|
||||
reg |= MDIO_PCS_CTRL2_10GBX;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
|
||||
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
reg &= ~MDIO_CTRL1_SPEEDSEL;
|
||||
reg |= MDIO_CTRL1_SPEED1G;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
|
||||
|
||||
xgbe_phy_pcs_power_cycle(pdata);
|
||||
|
||||
/* Set SerDes to 1G speed */
|
||||
xgbe_phy_start_ratechange(pdata);
|
||||
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
|
||||
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
|
||||
phy_data->cdr_rate[XGBE_SPEED_1000]);
|
||||
XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
|
||||
phy_data->tx_amp[XGBE_SPEED_1000]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
|
||||
phy_data->blwc[XGBE_SPEED_1000]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
|
||||
phy_data->pq_skew[XGBE_SPEED_1000]);
|
||||
XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
|
||||
phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
|
||||
XRXTX_IOWRITE(pdata, RXTX_REG22,
|
||||
phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
|
||||
|
||||
xgbe_phy_complete_ratechange(pdata);
|
||||
|
||||
axgbe_printf(2, "1GbE KX mode set\n");
|
||||
}
|
||||
|
||||
static enum xgbe_mode
|
||||
xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
enum xgbe_mode mode;
|
||||
unsigned int reg;
|
||||
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
|
||||
reg &= MDIO_PCS_CTRL2_TYPE;
|
||||
|
||||
if (reg == MDIO_PCS_CTRL2_10GBR) {
|
||||
mode = XGBE_MODE_KR;
|
||||
} else {
|
||||
if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
|
||||
mode = XGBE_MODE_KX_2500;
|
||||
else
|
||||
mode = XGBE_MODE_KX_1000;
|
||||
}
|
||||
|
||||
return (mode);
|
||||
}
|
||||
|
||||
static enum xgbe_mode
|
||||
xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
enum xgbe_mode mode;
|
||||
|
||||
/* If we are in KR switch to KX, and vice-versa */
|
||||
if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
|
||||
if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
|
||||
mode = XGBE_MODE_KX_2500;
|
||||
else
|
||||
mode = XGBE_MODE_KX_1000;
|
||||
} else {
|
||||
mode = XGBE_MODE_KR;
|
||||
}
|
||||
|
||||
return (mode);
|
||||
}
|
||||
|
||||
static enum xgbe_mode
|
||||
xgbe_phy_get_mode(struct xgbe_prv_data *pdata, int speed)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_1000:
|
||||
return ((phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
|
||||
? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN);
|
||||
case SPEED_2500:
|
||||
return ((phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
|
||||
? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN);
|
||||
case SPEED_10000:
|
||||
return (XGBE_MODE_KR);
|
||||
default:
|
||||
return (XGBE_MODE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case XGBE_MODE_KX_1000:
|
||||
xgbe_phy_kx_1000_mode(pdata);
|
||||
break;
|
||||
case XGBE_MODE_KX_2500:
|
||||
xgbe_phy_kx_2500_mode(pdata);
|
||||
break;
|
||||
case XGBE_MODE_KR:
|
||||
xgbe_phy_kr_mode(pdata);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_get_type(struct xgbe_prv_data *pdata, struct ifmediareq * ifmr)
|
||||
{
|
||||
|
||||
switch (pdata->phy.speed) {
|
||||
case SPEED_10000:
|
||||
ifmr->ifm_active |= IFM_10G_KR;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
ifmr->ifm_active |= IFM_2500_KX;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ifmr->ifm_active |= IFM_1000_KX;
|
||||
break;
|
||||
default:
|
||||
ifmr->ifm_active |= IFM_OTHER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
xgbe_phy_check_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode, bool advert)
|
||||
{
|
||||
|
||||
if (pdata->phy.autoneg == AUTONEG_ENABLE)
|
||||
return (advert);
|
||||
else {
|
||||
enum xgbe_mode cur_mode;
|
||||
|
||||
cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
|
||||
if (cur_mode == mode)
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
|
||||
{
|
||||
|
||||
switch (mode) {
|
||||
case XGBE_MODE_KX_1000:
|
||||
return (xgbe_phy_check_mode(pdata, mode,
|
||||
XGBE_ADV(&pdata->phy, 1000baseKX_Full)));
|
||||
case XGBE_MODE_KX_2500:
|
||||
return (xgbe_phy_check_mode(pdata, mode,
|
||||
XGBE_ADV(&pdata->phy, 2500baseX_Full)));
|
||||
case XGBE_MODE_KR:
|
||||
return (xgbe_phy_check_mode(pdata, mode,
|
||||
XGBE_ADV(&pdata->phy, 10000baseKR_Full)));
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
|
||||
switch (speed) {
|
||||
case SPEED_1000:
|
||||
if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
|
||||
return (false);
|
||||
return (true);
|
||||
case SPEED_2500:
|
||||
if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
|
||||
return (false);
|
||||
return (true);
|
||||
case SPEED_10000:
|
||||
return (true);
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
*an_restart = 0;
|
||||
|
||||
/* Link status is latched low, so read once to clear
|
||||
* and then read again to get current state
|
||||
*/
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
|
||||
|
||||
return ((reg & MDIO_STAT1_LSTATUS) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_stop(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
/* Nothing uniquely required for stop */
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_start(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
/* Nothing uniquely required for start */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_reset(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
unsigned int reg, count;
|
||||
|
||||
/* Perform a software reset of the PCS */
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
reg |= MDIO_CTRL1_RESET;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
|
||||
|
||||
count = 50;
|
||||
do {
|
||||
DELAY(20);
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
} while ((reg & MDIO_CTRL1_RESET) && --count);
|
||||
|
||||
if (reg & MDIO_CTRL1_RESET)
|
||||
return (-ETIMEDOUT);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_phy_exit(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
/* Nothing uniquely required for exit */
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_init(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data;
|
||||
|
||||
phy_data = malloc(sizeof(*phy_data), M_AXGBE, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Initialize supported features */
|
||||
XGBE_ZERO_SUP(&pdata->phy);
|
||||
XGBE_SET_SUP(&pdata->phy, Autoneg);
|
||||
XGBE_SET_SUP(&pdata->phy, Pause);
|
||||
XGBE_SET_SUP(&pdata->phy, Asym_Pause);
|
||||
XGBE_SET_SUP(&pdata->phy, Backplane);
|
||||
XGBE_SET_SUP(&pdata->phy, 10000baseKR_Full);
|
||||
switch (phy_data->speed_set) {
|
||||
case XGBE_SPEEDSET_1000_10000:
|
||||
XGBE_SET_SUP(&pdata->phy, 1000baseKX_Full);
|
||||
break;
|
||||
case XGBE_SPEEDSET_2500_10000:
|
||||
XGBE_SET_SUP(&pdata->phy, 2500baseX_Full);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
|
||||
XGBE_SET_SUP(&pdata->phy, 10000baseR_FEC);
|
||||
|
||||
pdata->phy_data = phy_data;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
|
||||
{
|
||||
struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
|
||||
|
||||
phy_impl->init = xgbe_phy_init;
|
||||
phy_impl->exit = xgbe_phy_exit;
|
||||
|
||||
phy_impl->reset = xgbe_phy_reset;
|
||||
phy_impl->start = xgbe_phy_start;
|
||||
phy_impl->stop = xgbe_phy_stop;
|
||||
|
||||
phy_impl->link_status = xgbe_phy_link_status;
|
||||
|
||||
phy_impl->valid_speed = xgbe_phy_valid_speed;
|
||||
|
||||
phy_impl->use_mode = xgbe_phy_use_mode;
|
||||
phy_impl->set_mode = xgbe_phy_set_mode;
|
||||
phy_impl->get_mode = xgbe_phy_get_mode;
|
||||
phy_impl->switch_mode = xgbe_phy_switch_mode;
|
||||
phy_impl->cur_mode = xgbe_phy_cur_mode;
|
||||
phy_impl->get_type = xgbe_phy_get_type;
|
||||
|
||||
phy_impl->an_mode = xgbe_phy_an_mode;
|
||||
|
||||
phy_impl->an_config = xgbe_phy_an_config;
|
||||
|
||||
phy_impl->an_advertising = xgbe_phy_an_advertising;
|
||||
|
||||
phy_impl->an_outcome = xgbe_phy_an_outcome;
|
||||
|
||||
phy_impl->kr_training_pre = xgbe_phy_kr_training_pre;
|
||||
phy_impl->kr_training_post = xgbe_phy_kr_training_post;
|
||||
}
|
3771
sys/dev/axgbe/xgbe-phy-v2.c
Normal file
3771
sys/dev/axgbe/xgbe-phy-v2.c
Normal file
File diff suppressed because it is too large
Load Diff
276
sys/dev/axgbe/xgbe-ptp.c
Normal file
276
sys/dev/axgbe/xgbe-ptp.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* AMD 10Gb Ethernet driver
|
||||
*
|
||||
* This file is available to you under your choice of the following two
|
||||
* licenses:
|
||||
*
|
||||
* License 1: GPLv2
|
||||
*
|
||||
* Copyright (c) 2014 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This file is free software; you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* License 2: Modified BSD
|
||||
*
|
||||
* Copyright (c) 2014 Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Advanced Micro Devices, Inc. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
* The Synopsys DWC ETHER XGMAC Software Driver and documentation
|
||||
* (hereinafter "Software") is an unsupported proprietary work of Synopsys,
|
||||
* Inc. unless otherwise expressly agreed to in writing between Synopsys
|
||||
* and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product
|
||||
* under any End User Software License Agreement or Agreement for Licensed
|
||||
* Product with Synopsys or any supplement thereto. Permission is hereby
|
||||
* granted, free of charge, to any person obtaining a copy of this software
|
||||
* annotated with this license and the Software, to deal in the Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
|
||||
* BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "xgbe.h"
|
||||
|
||||
static u64 xgbe_cc_read(const struct cyclecounter *cc)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(cc,
|
||||
struct xgbe_prv_data,
|
||||
tstamp_cc);
|
||||
u64 nsec;
|
||||
|
||||
nsec = pdata->hw_if.get_tstamp_time(pdata);
|
||||
|
||||
return (nsec);
|
||||
}
|
||||
|
||||
static int xgbe_adjfreq(struct ptp_clock_info *info, s32 delta)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(info,
|
||||
struct xgbe_prv_data,
|
||||
ptp_clock_info);
|
||||
unsigned long flags;
|
||||
u64 adjust;
|
||||
u32 addend, diff;
|
||||
unsigned int neg_adjust = 0;
|
||||
|
||||
if (delta < 0) {
|
||||
neg_adjust = 1;
|
||||
delta = -delta;
|
||||
}
|
||||
|
||||
adjust = pdata->tstamp_addend;
|
||||
adjust *= delta;
|
||||
diff = div_u64(adjust, 1000000000UL);
|
||||
|
||||
addend = (neg_adjust) ? pdata->tstamp_addend - diff :
|
||||
pdata->tstamp_addend + diff;
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
|
||||
pdata->hw_if.update_tstamp_addend(pdata, addend);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(info,
|
||||
struct xgbe_prv_data,
|
||||
ptp_clock_info);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
timecounter_adjtime(&pdata->tstamp_tc, delta);
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(info,
|
||||
struct xgbe_prv_data,
|
||||
ptp_clock_info);
|
||||
unsigned long flags;
|
||||
u64 nsec;
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
|
||||
nsec = timecounter_read(&pdata->tstamp_tc);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
|
||||
*ts = ns_to_timespec64(nsec);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_settime(struct ptp_clock_info *info,
|
||||
const struct timespec64 *ts)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(info,
|
||||
struct xgbe_prv_data,
|
||||
ptp_clock_info);
|
||||
unsigned long flags;
|
||||
u64 nsec;
|
||||
|
||||
nsec = timespec64_to_ns(ts);
|
||||
|
||||
spin_lock_irqsave(&pdata->tstamp_lock, flags);
|
||||
|
||||
timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xgbe_enable(struct ptp_clock_info *info,
|
||||
void *request, int on)
|
||||
{
|
||||
return (-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
void xgbe_ptp_register(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct ptp_clock_info *info = &pdata->ptp_clock_info;
|
||||
//struct ptp_clock *clock;
|
||||
struct cyclecounter *cc = &pdata->tstamp_cc;
|
||||
u64 dividend;
|
||||
|
||||
snprintf(info->name, sizeof(info->name), "axgbe-ptp");
|
||||
//info->owner = THIS_MODULE;
|
||||
info->max_adj = pdata->ptpclk_rate;
|
||||
info->adjfreq = xgbe_adjfreq;
|
||||
info->adjtime = xgbe_adjtime;
|
||||
info->gettime64 = xgbe_gettime;
|
||||
info->settime64 = xgbe_settime;
|
||||
info->enable = xgbe_enable;
|
||||
#if 0
|
||||
clock = ptp_clock_register(info, pdata->dev);
|
||||
if (IS_ERR(clock)) {
|
||||
dev_err(pdata->dev, "ptp_clock_register failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pdata->ptp_clock = clock;
|
||||
#endif
|
||||
/* Calculate the addend:
|
||||
* addend = 2^32 / (PTP ref clock / 50Mhz)
|
||||
* = (2^32 * 50Mhz) / PTP ref clock
|
||||
*/
|
||||
dividend = 50000000;
|
||||
dividend <<= 32;
|
||||
pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
|
||||
|
||||
/* Setup the timecounter */
|
||||
cc->read = xgbe_cc_read;
|
||||
cc->mask = CLOCKSOURCE_MASK(64);
|
||||
cc->mult = 1;
|
||||
cc->shift = 0;
|
||||
|
||||
timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
|
||||
ktime_to_ns(ktime_get_real()));
|
||||
|
||||
/* Disable all timestamping to start */
|
||||
XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
|
||||
pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
|
||||
pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
}
|
||||
|
||||
void xgbe_ptp_unregister(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
#if 0
|
||||
if (pdata->ptp_clock)
|
||||
ptp_clock_unregister(pdata->ptp_clock);
|
||||
#endif
|
||||
}
|
1715
sys/dev/axgbe/xgbe-sysctl.c
Normal file
1715
sys/dev/axgbe/xgbe-sysctl.c
Normal file
File diff suppressed because it is too large
Load Diff
777
sys/dev/axgbe/xgbe-txrx.c
Normal file
777
sys/dev/axgbe/xgbe-txrx.c
Normal file
@ -0,0 +1,777 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Contact Information :
|
||||
* Rajesh Kumar <rajesh1.kumar@amd.com>
|
||||
* Shreyank Amartya <Shreyank.Amartya@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "xgbe.h"
|
||||
#include "xgbe-common.h"
|
||||
|
||||
/*
|
||||
* IFLIB interfaces
|
||||
*/
|
||||
static int axgbe_isc_txd_encap(void *, if_pkt_info_t);
|
||||
static void axgbe_isc_txd_flush(void *, uint16_t, qidx_t);
|
||||
static int axgbe_isc_txd_credits_update(void *, uint16_t, bool);
|
||||
static void axgbe_isc_rxd_refill(void *, if_rxd_update_t);
|
||||
static void axgbe_isc_rxd_flush(void *, uint16_t, uint8_t, qidx_t);
|
||||
static int axgbe_isc_rxd_available(void *, uint16_t, qidx_t, qidx_t);
|
||||
static int axgbe_isc_rxd_pkt_get(void *, if_rxd_info_t);
|
||||
|
||||
struct if_txrx axgbe_txrx = {
|
||||
.ift_txd_encap = axgbe_isc_txd_encap,
|
||||
.ift_txd_flush = axgbe_isc_txd_flush,
|
||||
.ift_txd_credits_update = axgbe_isc_txd_credits_update,
|
||||
.ift_rxd_available = axgbe_isc_rxd_available,
|
||||
.ift_rxd_pkt_get = axgbe_isc_rxd_pkt_get,
|
||||
.ift_rxd_refill = axgbe_isc_rxd_refill,
|
||||
.ift_rxd_flush = axgbe_isc_rxd_flush,
|
||||
.ift_legacy_intr = NULL
|
||||
};
|
||||
|
||||
static void
|
||||
xgbe_print_pkt_info(struct xgbe_prv_data *pdata, if_pkt_info_t pi)
|
||||
{
|
||||
|
||||
axgbe_printf(1, "------Packet Info Start------\n");
|
||||
axgbe_printf(1, "pi len: %d qsidx: %d nsegs: %d ndescs: %d flags: %x pidx: %d\n",
|
||||
pi->ipi_len, pi->ipi_qsidx, pi->ipi_nsegs, pi->ipi_ndescs, pi->ipi_flags, pi->ipi_pidx);
|
||||
axgbe_printf(1, "pi new_pidx: %d csum_flags: %x mflags: %x vtag: %d\n",
|
||||
pi->ipi_new_pidx, pi->ipi_csum_flags, pi->ipi_mflags, pi->ipi_vtag);
|
||||
axgbe_printf(1, "pi etype: %d ehdrlen: %d ip_hlen: %d ipproto: %d\n",
|
||||
pi->ipi_etype, pi->ipi_ehdrlen, pi->ipi_ip_hlen, pi->ipi_ipproto);
|
||||
axgbe_printf(1, "pi tcp_hlen: %d tcp_hflags: %x tcp_seq: %d tso_segsz %d\n",
|
||||
pi->ipi_tcp_hlen, pi->ipi_tcp_hflags, pi->ipi_tcp_seq, pi->ipi_tso_segsz);
|
||||
}
|
||||
|
||||
static bool
|
||||
axgbe_ctx_desc_setup(struct xgbe_prv_data *pdata, struct xgbe_ring *ring,
|
||||
if_pkt_info_t pi)
|
||||
{
|
||||
struct xgbe_ring_desc *rdesc;
|
||||
struct xgbe_ring_data *rdata;
|
||||
bool inc_cur = false;
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
||||
rdesc = rdata->rdesc;
|
||||
|
||||
axgbe_printf(1, "ipi_tso_segsz %d cur_mss %d idx %d\n",
|
||||
pi->ipi_tso_segsz, ring->tx.cur_mss, ring->cur);
|
||||
|
||||
axgbe_printf(1, "ipi_vtag 0x%x cur_vlan_ctag 0x%x\n",
|
||||
pi->ipi_vtag, ring->tx.cur_vlan_ctag);
|
||||
|
||||
if ((pi->ipi_csum_flags & CSUM_TSO) &&
|
||||
(pi->ipi_tso_segsz != ring->tx.cur_mss)) {
|
||||
/*
|
||||
* Set TSO maximum segment size
|
||||
* Mark as context descriptor
|
||||
* Indicate this descriptor contains MSS
|
||||
*/
|
||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_CONTEXT_DESC2,
|
||||
MSS, pi->ipi_tso_segsz);
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, CTXT, 1);
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, TCMSSV, 1);
|
||||
ring->tx.cur_mss = pi->ipi_tso_segsz;
|
||||
inc_cur = true;
|
||||
}
|
||||
|
||||
if (pi->ipi_vtag && (pi->ipi_vtag != ring->tx.cur_vlan_ctag)) {
|
||||
/*
|
||||
* Mark it as context descriptor
|
||||
* Set the VLAN tag
|
||||
* Indicate this descriptor contains the VLAN tag
|
||||
*/
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, CTXT, 1);
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3,
|
||||
VT, pi->ipi_vtag);
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, VLTV, 1);
|
||||
ring->tx.cur_vlan_ctag = pi->ipi_vtag;
|
||||
inc_cur = true;
|
||||
}
|
||||
|
||||
return (inc_cur);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
axgbe_calculate_tx_parms(struct xgbe_prv_data *pdata, if_pkt_info_t pi,
|
||||
struct xgbe_packet_data *packet)
|
||||
{
|
||||
uint32_t tcp_payload_len = 0, bytes = 0;
|
||||
uint16_t max_len, hlen, payload_len, pkts = 0;
|
||||
|
||||
packet->tx_packets = packet->tx_bytes = 0;
|
||||
|
||||
hlen = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen;
|
||||
if (pi->ipi_csum_flags & CSUM_TSO) {
|
||||
|
||||
tcp_payload_len = pi->ipi_len - hlen;
|
||||
axgbe_printf(1, "%s: ipi_len %x elen %d iplen %d tcplen %d\n",
|
||||
__func__, pi->ipi_len, pi->ipi_ehdrlen, pi->ipi_ip_hlen,
|
||||
pi->ipi_tcp_hlen);
|
||||
|
||||
max_len = if_getmtu(pdata->netdev) + ETH_HLEN;
|
||||
if (pi->ipi_vtag)
|
||||
max_len += VLAN_HLEN;
|
||||
|
||||
while (tcp_payload_len) {
|
||||
|
||||
payload_len = max_len - hlen;
|
||||
payload_len = min(payload_len, tcp_payload_len);
|
||||
tcp_payload_len -= payload_len;
|
||||
pkts++;
|
||||
bytes += (hlen + payload_len);
|
||||
axgbe_printf(1, "%s: max_len %d payload_len %d "
|
||||
"tcp_len %d\n", __func__, max_len, payload_len,
|
||||
tcp_payload_len);
|
||||
}
|
||||
} else {
|
||||
pkts = 1;
|
||||
bytes = pi->ipi_len;
|
||||
}
|
||||
|
||||
packet->tx_packets = pkts;
|
||||
packet->tx_bytes = bytes;
|
||||
|
||||
axgbe_printf(1, "%s: packets %d bytes %d hlen %d\n", __func__,
|
||||
packet->tx_packets, packet->tx_bytes, hlen);
|
||||
|
||||
return (hlen);
|
||||
}
|
||||
|
||||
static int
|
||||
axgbe_isc_txd_encap(void *arg, if_pkt_info_t pi)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_channel *channel;
|
||||
struct xgbe_ring *ring;
|
||||
struct xgbe_ring_desc *rdesc;
|
||||
struct xgbe_ring_data *rdata;
|
||||
struct xgbe_packet_data *packet;
|
||||
unsigned int cur, start, tx_set_ic;
|
||||
uint16_t offset, hlen, datalen, tcp_payload_len = 0;
|
||||
int cur_seg = 0;
|
||||
|
||||
xgbe_print_pkt_info(pdata, pi);
|
||||
|
||||
channel = pdata->channel[pi->ipi_qsidx];
|
||||
ring = channel->tx_ring;
|
||||
packet = &ring->packet_data;
|
||||
cur = start = ring->cur;
|
||||
|
||||
axgbe_printf(1, "--> %s: txq %d cur %d dirty %d\n",
|
||||
__func__, pi->ipi_qsidx, ring->cur, ring->dirty);
|
||||
|
||||
MPASS(pi->ipi_len != 0);
|
||||
if (__predict_false(pi->ipi_len == 0)) {
|
||||
axgbe_error("empty packet received from stack\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
MPASS(ring->cur == pi->ipi_pidx);
|
||||
if (__predict_false(ring->cur != pi->ipi_pidx)) {
|
||||
axgbe_error("--> %s: cur(%d) ne pidx(%d)\n", __func__,
|
||||
ring->cur, pi->ipi_pidx);
|
||||
}
|
||||
|
||||
/* Determine if an interrupt should be generated for this Tx:
|
||||
* Interrupt:
|
||||
* - Tx frame count exceeds the frame count setting
|
||||
* - Addition of Tx frame count to the frame count since the
|
||||
* last interrupt was set exceeds the frame count setting
|
||||
* No interrupt:
|
||||
* - No frame count setting specified (ethtool -C ethX tx-frames 0)
|
||||
* - Addition of Tx frame count to the frame count since the
|
||||
* last interrupt was set does not exceed the frame count setting
|
||||
*/
|
||||
memset(packet, 0, sizeof(*packet));
|
||||
hlen = axgbe_calculate_tx_parms(pdata, pi, packet);
|
||||
axgbe_printf(1, "%s: ipi_len %d tx_pkts %d tx_bytes %d hlen %d\n",
|
||||
__func__, pi->ipi_len, packet->tx_packets, packet->tx_bytes, hlen);
|
||||
|
||||
ring->coalesce_count += packet->tx_packets;
|
||||
if (!pdata->tx_frames)
|
||||
tx_set_ic = 0;
|
||||
else if (packet->tx_packets > pdata->tx_frames)
|
||||
tx_set_ic = 1;
|
||||
else if ((ring->coalesce_count % pdata->tx_frames) < (packet->tx_packets))
|
||||
tx_set_ic = 1;
|
||||
else
|
||||
tx_set_ic = 0;
|
||||
|
||||
/* Add Context descriptor if needed (for TSO, VLAN cases) */
|
||||
if (axgbe_ctx_desc_setup(pdata, ring, pi))
|
||||
cur++;
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, cur);
|
||||
rdesc = rdata->rdesc;
|
||||
|
||||
axgbe_printf(1, "%s: cur %d lo 0x%lx hi 0x%lx ds_len 0x%x "
|
||||
"ipi_len 0x%x\n", __func__, cur,
|
||||
lower_32_bits(pi->ipi_segs[cur_seg].ds_addr),
|
||||
upper_32_bits(pi->ipi_segs[cur_seg].ds_addr),
|
||||
(int)pi->ipi_segs[cur_seg].ds_len, pi->ipi_len);
|
||||
|
||||
/* Update buffer address (for TSO this is the header) */
|
||||
rdesc->desc0 = cpu_to_le32(lower_32_bits(pi->ipi_segs[cur_seg].ds_addr));
|
||||
rdesc->desc1 = cpu_to_le32(upper_32_bits(pi->ipi_segs[cur_seg].ds_addr));
|
||||
|
||||
/* Update the buffer length */
|
||||
if (hlen == 0)
|
||||
hlen = pi->ipi_segs[cur_seg].ds_len;
|
||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L, hlen);
|
||||
|
||||
/* VLAN tag insertion check */
|
||||
if (pi->ipi_vtag) {
|
||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, VTIR,
|
||||
TX_NORMAL_DESC2_VLAN_INSERT);
|
||||
}
|
||||
|
||||
/* Mark it as First Descriptor */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1);
|
||||
|
||||
/* Mark it as a NORMAL descriptor */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0);
|
||||
|
||||
/*
|
||||
* Set the OWN bit if this is not the first descriptor. For first
|
||||
* descriptor, OWN bit will be set at last so that hardware will
|
||||
* process the descriptors only after the OWN bit for the first
|
||||
* descriptor is set
|
||||
*/
|
||||
if (cur != start)
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
|
||||
|
||||
if (pi->ipi_csum_flags & CSUM_TSO) {
|
||||
/* Enable TSO */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TSE, 1);
|
||||
|
||||
tcp_payload_len = pi->ipi_len - hlen;
|
||||
|
||||
/* Set TCP payload length*/
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPPL,
|
||||
tcp_payload_len);
|
||||
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN,
|
||||
pi->ipi_tcp_hlen/4);
|
||||
|
||||
axgbe_printf(1, "tcp_payload %d tcp_hlen %d\n", tcp_payload_len,
|
||||
pi->ipi_tcp_hlen/4);
|
||||
} else {
|
||||
/* Enable CRC and Pad Insertion */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0);
|
||||
|
||||
/* Enable HW CSUM*/
|
||||
if (pi->ipi_csum_flags)
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CIC, 0x3);
|
||||
|
||||
/* Set total length to be transmitted */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FL, pi->ipi_len);
|
||||
}
|
||||
|
||||
cur++;
|
||||
|
||||
for (cur_seg = 0 ; cur_seg < pi->ipi_nsegs ; cur_seg++) {
|
||||
|
||||
if (cur_seg == 0) {
|
||||
offset = hlen;
|
||||
datalen = pi->ipi_segs[cur_seg].ds_len - hlen;
|
||||
} else {
|
||||
offset = 0;
|
||||
datalen = pi->ipi_segs[cur_seg].ds_len;
|
||||
}
|
||||
|
||||
if (datalen) {
|
||||
rdata = XGBE_GET_DESC_DATA(ring, cur);
|
||||
rdesc = rdata->rdesc;
|
||||
|
||||
|
||||
/* Update buffer address */
|
||||
rdesc->desc0 =
|
||||
cpu_to_le32(lower_32_bits(pi->ipi_segs[cur_seg].ds_addr + offset));
|
||||
rdesc->desc1 =
|
||||
cpu_to_le32(upper_32_bits(pi->ipi_segs[cur_seg].ds_addr + offset));
|
||||
|
||||
/* Update the buffer length */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L, datalen);
|
||||
|
||||
/* Set OWN bit */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
|
||||
|
||||
/* Mark it as NORMAL descriptor */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0);
|
||||
|
||||
/* Enable HW CSUM*/
|
||||
if (pi->ipi_csum_flags)
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CIC, 0x3);
|
||||
|
||||
axgbe_printf(1, "%s: cur %d lo 0x%lx hi 0x%lx ds_len 0x%x "
|
||||
"ipi_len 0x%x\n", __func__, cur,
|
||||
lower_32_bits(pi->ipi_segs[cur_seg].ds_addr),
|
||||
upper_32_bits(pi->ipi_segs[cur_seg].ds_addr),
|
||||
(int)pi->ipi_segs[cur_seg].ds_len, pi->ipi_len);
|
||||
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set LAST bit for the last descriptor */
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1);
|
||||
|
||||
/* Set IC bit based on Tx coalescing settings */
|
||||
if (tx_set_ic)
|
||||
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
|
||||
|
||||
wmb();
|
||||
|
||||
/* Set OWN bit for the first descriptor */
|
||||
rdata = XGBE_GET_DESC_DATA(ring, start);
|
||||
rdesc = rdata->rdesc;
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
|
||||
|
||||
ring->cur = pi->ipi_new_pidx = (cur & (ring->rdesc_count - 1));
|
||||
|
||||
axgbe_printf(1, "<-- %s: end cur %d dirty %d\n", __func__, ring->cur,
|
||||
ring->dirty);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
axgbe_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_channel *channel = pdata->channel[txqid];
|
||||
struct xgbe_ring *ring = channel->tx_ring;
|
||||
struct xgbe_ring_data *rdata = XGBE_GET_DESC_DATA(ring, pidx);
|
||||
|
||||
axgbe_printf(1, "--> %s: flush txq %d pidx %d cur %d dirty %d\n",
|
||||
__func__, txqid, pidx, ring->cur, ring->dirty);
|
||||
|
||||
MPASS(ring->cur == pidx);
|
||||
if (__predict_false(ring->cur != pidx)) {
|
||||
axgbe_error("--> %s: cur(%d) ne pidx(%d)\n", __func__,
|
||||
ring->cur, pidx);
|
||||
}
|
||||
|
||||
wmb();
|
||||
|
||||
/* Ring Doorbell */
|
||||
if (XGMAC_DMA_IOREAD(channel, DMA_CH_TDTR_LO) !=
|
||||
lower_32_bits(rdata->rdata_paddr)) {
|
||||
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
|
||||
lower_32_bits(rdata->rdata_paddr));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
axgbe_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_hw_if *hw_if = &sc->pdata.hw_if;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_channel *channel = pdata->channel[txqid];
|
||||
struct xgbe_ring *ring = channel->tx_ring;
|
||||
struct xgbe_ring_data *rdata;
|
||||
int processed = 0;
|
||||
|
||||
axgbe_printf(1, "%s: txq %d clear %d cur %d dirty %d\n",
|
||||
__func__, txqid, clear, ring->cur, ring->dirty);
|
||||
|
||||
if (__predict_false(ring->cur == ring->dirty)) {
|
||||
axgbe_printf(1, "<-- %s: cur(%d) equals dirty(%d)\n",
|
||||
__func__, ring->cur, ring->dirty);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Check whether the first dirty descriptor is Tx complete */
|
||||
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
|
||||
if (!hw_if->tx_complete(rdata->rdesc)) {
|
||||
axgbe_printf(1, "<-- %s: (dirty %d)\n", __func__, ring->dirty);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If clear is false just let the caller know that there
|
||||
* are descriptors to reclaim
|
||||
*/
|
||||
if (!clear) {
|
||||
axgbe_printf(1, "<-- %s: (!clear)\n", __func__);
|
||||
return (1);
|
||||
}
|
||||
|
||||
do {
|
||||
hw_if->tx_desc_reset(rdata);
|
||||
processed++;
|
||||
ring->dirty = (ring->dirty + 1) & (ring->rdesc_count - 1);
|
||||
|
||||
/*
|
||||
* tx_complete will return true for unused descriptors also.
|
||||
* so, check tx_complete only until used descriptors.
|
||||
*/
|
||||
if (ring->cur == ring->dirty)
|
||||
break;
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
|
||||
} while (hw_if->tx_complete(rdata->rdesc));
|
||||
|
||||
axgbe_printf(1, "<-- %s: processed %d cur %d dirty %d\n", __func__,
|
||||
processed, ring->cur, ring->dirty);
|
||||
|
||||
return (processed);
|
||||
}
|
||||
|
||||
static void
|
||||
axgbe_isc_rxd_refill(void *arg, if_rxd_update_t iru)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_channel *channel = pdata->channel[iru->iru_qsidx];
|
||||
struct xgbe_ring *ring = channel->rx_ring;
|
||||
struct xgbe_ring_data *rdata;
|
||||
struct xgbe_ring_desc *rdesc;
|
||||
unsigned int rx_usecs = pdata->rx_usecs;
|
||||
unsigned int rx_frames = pdata->rx_frames;
|
||||
unsigned int inte;
|
||||
uint8_t count = iru->iru_count;
|
||||
int i, j;
|
||||
|
||||
axgbe_printf(1, "--> %s: rxq %d fl %d pidx %d count %d ring cur %d "
|
||||
"dirty %d\n", __func__, iru->iru_qsidx, iru->iru_flidx,
|
||||
iru->iru_pidx, count, ring->cur, ring->dirty);
|
||||
|
||||
for (i = iru->iru_pidx, j = 0 ; j < count ; i++, j++) {
|
||||
|
||||
if (i == XGBE_RX_DESC_CNT_DEFAULT)
|
||||
i = 0;
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, i);
|
||||
rdesc = rdata->rdesc;
|
||||
|
||||
if (__predict_false(XGMAC_GET_BITS_LE(rdesc->desc3,
|
||||
RX_NORMAL_DESC3, OWN))) {
|
||||
axgbe_error("%s: refill clash, cur %d dirty %d index %d"
|
||||
"pidx %d\n", __func__, ring->cur, ring->dirty, j, i);
|
||||
}
|
||||
|
||||
/* Assuming split header is enabled */
|
||||
if (iru->iru_flidx == 0) {
|
||||
|
||||
/* Fill header/buffer1 address */
|
||||
rdesc->desc0 =
|
||||
cpu_to_le32(lower_32_bits(iru->iru_paddrs[j]));
|
||||
rdesc->desc1 =
|
||||
cpu_to_le32(upper_32_bits(iru->iru_paddrs[j]));
|
||||
} else {
|
||||
|
||||
/* Fill data/buffer2 address */
|
||||
rdesc->desc2 =
|
||||
cpu_to_le32(lower_32_bits(iru->iru_paddrs[j]));
|
||||
rdesc->desc3 =
|
||||
cpu_to_le32(upper_32_bits(iru->iru_paddrs[j]));
|
||||
|
||||
if (!rx_usecs && !rx_frames) {
|
||||
/* No coalescing, interrupt for every descriptor */
|
||||
inte = 1;
|
||||
} else {
|
||||
/* Set interrupt based on Rx frame coalescing setting */
|
||||
if (rx_frames &&
|
||||
!(((ring->dirty + 1) &(ring->rdesc_count - 1)) % rx_frames))
|
||||
inte = 1;
|
||||
else
|
||||
inte = 0;
|
||||
}
|
||||
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte);
|
||||
|
||||
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN, 1);
|
||||
|
||||
wmb();
|
||||
|
||||
ring->dirty = ((ring->dirty + 1) & (ring->rdesc_count - 1));
|
||||
}
|
||||
}
|
||||
|
||||
axgbe_printf(1, "<-- %s: rxq: %d cur: %d dirty: %d\n", __func__,
|
||||
channel->queue_index, ring->cur, ring->dirty);
|
||||
}
|
||||
|
||||
static void
|
||||
axgbe_isc_rxd_flush(void *arg, uint16_t qsidx, uint8_t flidx, qidx_t pidx)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_channel *channel = pdata->channel[qsidx];
|
||||
struct xgbe_ring *ring = channel->rx_ring;
|
||||
struct xgbe_ring_data *rdata;
|
||||
|
||||
axgbe_printf(1, "--> %s: rxq %d fl %d pidx %d cur %d dirty %d\n",
|
||||
__func__, qsidx, flidx, pidx, ring->cur, ring->dirty);
|
||||
|
||||
if (flidx == 1) {
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, pidx);
|
||||
|
||||
XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
|
||||
lower_32_bits(rdata->rdata_paddr));
|
||||
}
|
||||
|
||||
wmb();
|
||||
}
|
||||
|
||||
static int
|
||||
axgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t idx, qidx_t budget)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_channel *channel = pdata->channel[qsidx];
|
||||
struct xgbe_ring *ring = channel->rx_ring;
|
||||
struct xgbe_ring_data *rdata;
|
||||
struct xgbe_ring_desc *rdesc;
|
||||
unsigned int cur;
|
||||
int count;
|
||||
uint8_t incomplete = 1, context_next = 0, running = 0;
|
||||
|
||||
axgbe_printf(1, "--> %s: rxq %d idx %d budget %d cur %d dirty %d\n",
|
||||
__func__, qsidx, idx, budget, ring->cur, ring->dirty);
|
||||
|
||||
cur = ring->cur;
|
||||
for (count = 0; count <= budget; ) {
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, cur);
|
||||
rdesc = rdata->rdesc;
|
||||
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN))
|
||||
break;
|
||||
|
||||
running = 1;
|
||||
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD))
|
||||
incomplete = 0;
|
||||
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CDA))
|
||||
context_next = 1;
|
||||
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CTXT))
|
||||
context_next = 0;
|
||||
|
||||
cur = (cur + 1) & (ring->rdesc_count - 1);
|
||||
|
||||
if (incomplete || context_next)
|
||||
continue;
|
||||
|
||||
/* Increment pkt count & reset variables for next full packet */
|
||||
count++;
|
||||
incomplete = 1;
|
||||
context_next = 0;
|
||||
running = 0;
|
||||
}
|
||||
|
||||
axgbe_printf(1, "--> %s: rxq %d cur %d incomp %d con_next %d running %d "
|
||||
"count %d\n", __func__, qsidx, cur, incomplete, context_next,
|
||||
running, count);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
xgbe_rx_buf1_len(struct xgbe_prv_data *pdata, struct xgbe_ring_data *rdata,
|
||||
struct xgbe_packet_data *packet)
|
||||
{
|
||||
|
||||
/* Always zero if not the first descriptor */
|
||||
if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST)) {
|
||||
axgbe_printf(1, "%s: Not First\n", __func__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* First descriptor with split header, return header length */
|
||||
if (rdata->rx.hdr_len) {
|
||||
axgbe_printf(1, "%s: hdr_len %d\n", __func__, rdata->rx.hdr_len);
|
||||
return (rdata->rx.hdr_len);
|
||||
}
|
||||
|
||||
/* First descriptor but not the last descriptor and no split header,
|
||||
* so the full buffer was used
|
||||
*/
|
||||
if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) {
|
||||
axgbe_printf(1, "%s: Not last %d\n", __func__,
|
||||
pdata->rx_buf_size);
|
||||
return (256);
|
||||
}
|
||||
|
||||
/* First descriptor and last descriptor and no split header, so
|
||||
* calculate how much of the buffer was used
|
||||
*/
|
||||
axgbe_printf(1, "%s: pkt_len %d buf_size %d\n", __func__, rdata->rx.len,
|
||||
pdata->rx_buf_size);
|
||||
|
||||
return (min_t(unsigned int, 256, rdata->rx.len));
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
xgbe_rx_buf2_len(struct xgbe_prv_data *pdata, struct xgbe_ring_data *rdata,
|
||||
struct xgbe_packet_data *packet, unsigned int len)
|
||||
{
|
||||
|
||||
/* Always the full buffer if not the last descriptor */
|
||||
if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST)) {
|
||||
axgbe_printf(1, "%s: Not last %d\n", __func__, pdata->rx_buf_size);
|
||||
return (pdata->rx_buf_size);
|
||||
}
|
||||
|
||||
/* Last descriptor so calculate how much of the buffer was used
|
||||
* for the last bit of data
|
||||
*/
|
||||
return ((rdata->rx.len != 0)? (rdata->rx.len - len) : 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
axgbe_add_frag(struct xgbe_prv_data *pdata, if_rxd_info_t ri, int idx, int len,
|
||||
int pos, int flid)
|
||||
{
|
||||
axgbe_printf(2, "idx %d len %d pos %d flid %d\n", idx, len, pos, flid);
|
||||
ri->iri_frags[pos].irf_flid = flid;
|
||||
ri->iri_frags[pos].irf_idx = idx;
|
||||
ri->iri_frags[pos].irf_len = len;
|
||||
}
|
||||
|
||||
static int
|
||||
axgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
|
||||
{
|
||||
struct axgbe_if_softc *sc = (struct axgbe_if_softc*)arg;
|
||||
struct xgbe_prv_data *pdata = &sc->pdata;
|
||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
struct xgbe_channel *channel = pdata->channel[ri->iri_qsidx];
|
||||
struct xgbe_ring *ring = channel->rx_ring;
|
||||
struct xgbe_packet_data *packet = &ring->packet_data;
|
||||
struct xgbe_ring_data *rdata;
|
||||
unsigned int last, context_next, context;
|
||||
unsigned int buf1_len, buf2_len, max_len, len = 0, prev_cur;
|
||||
int i = 0;
|
||||
|
||||
axgbe_printf(2, "%s: rxq %d cidx %d cur %d dirty %d\n", __func__,
|
||||
ri->iri_qsidx, ri->iri_cidx, ring->cur, ring->dirty);
|
||||
|
||||
memset(packet, 0, sizeof(struct xgbe_packet_data));
|
||||
|
||||
while (1) {
|
||||
|
||||
read_again:
|
||||
if (hw_if->dev_read(channel)) {
|
||||
axgbe_printf(2, "<-- %s: OWN bit seen on %d\n",
|
||||
__func__, ring->cur);
|
||||
break;
|
||||
}
|
||||
|
||||
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
||||
prev_cur = ring->cur;
|
||||
ring->cur = (ring->cur + 1) & (ring->rdesc_count - 1);
|
||||
|
||||
last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
LAST);
|
||||
|
||||
context_next = XGMAC_GET_BITS(packet->attributes,
|
||||
RX_PACKET_ATTRIBUTES, CONTEXT_NEXT);
|
||||
|
||||
context = XGMAC_GET_BITS(packet->attributes,
|
||||
RX_PACKET_ATTRIBUTES, CONTEXT);
|
||||
|
||||
if (!context) {
|
||||
/* Get the data length in the descriptor buffers */
|
||||
buf1_len = xgbe_rx_buf1_len(pdata, rdata, packet);
|
||||
len += buf1_len;
|
||||
buf2_len = xgbe_rx_buf2_len(pdata, rdata, packet, len);
|
||||
len += buf2_len;
|
||||
} else
|
||||
buf1_len = buf2_len = 0;
|
||||
|
||||
if (packet->errors)
|
||||
axgbe_printf(1, "%s: last %d context %d con_next %d buf1 %d "
|
||||
"buf2 %d len %d frags %d error %d\n", __func__, last, context,
|
||||
context_next, buf1_len, buf2_len, len, i, packet->errors);
|
||||
|
||||
axgbe_add_frag(pdata, ri, prev_cur, buf1_len, i, 0);
|
||||
i++;
|
||||
axgbe_add_frag(pdata, ri, prev_cur, buf2_len, i, 1);
|
||||
i++;
|
||||
|
||||
if (!last || context_next)
|
||||
goto read_again;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CSUM_DONE)) {
|
||||
ri->iri_csum_flags |= CSUM_IP_CHECKED;
|
||||
ri->iri_csum_flags |= CSUM_IP_VALID;
|
||||
axgbe_printf(2, "%s: csum flags 0x%x\n", __func__, ri->iri_csum_flags);
|
||||
}
|
||||
|
||||
max_len = if_getmtu(pdata->netdev) + ETH_HLEN;
|
||||
if (XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, VLAN_CTAG)) {
|
||||
ri->iri_flags |= M_VLANTAG;
|
||||
ri->iri_vtag = packet->vlan_ctag;
|
||||
max_len += VLAN_HLEN;
|
||||
axgbe_printf(2, "%s: iri_flags 0x%x vtag 0x%x\n", __func__,
|
||||
ri->iri_flags, ri->iri_vtag);
|
||||
}
|
||||
|
||||
|
||||
if (XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, RSS_HASH)) {
|
||||
ri->iri_flowid = packet->rss_hash;
|
||||
ri->iri_rsstype = packet->rss_hash_type;
|
||||
axgbe_printf(2, "%s: hash 0x%x/0x%x rsstype 0x%x/0x%x\n",
|
||||
__func__, packet->rss_hash, ri->iri_flowid,
|
||||
packet->rss_hash_type, ri->iri_rsstype);
|
||||
}
|
||||
|
||||
if (__predict_false(len == 0))
|
||||
axgbe_error("%s: Zero len packet\n", __func__);
|
||||
|
||||
if (__predict_false(len > max_len))
|
||||
axgbe_error("%s: Big packet %d/%d\n", __func__, len, max_len);
|
||||
|
||||
if (__predict_false(packet->errors))
|
||||
axgbe_printf(1, "<-- %s: rxq: %d len: %d frags: %d cidx %d cur: %d "
|
||||
"dirty: %d error 0x%x\n", __func__, ri->iri_qsidx, len, i,
|
||||
ri->iri_cidx, ring->cur, ring->dirty, packet->errors);
|
||||
|
||||
axgbe_printf(1, "%s: Packet len %d frags %d\n", __func__, len, i);
|
||||
|
||||
ri->iri_len = len;
|
||||
ri->iri_nfrags = i;
|
||||
|
||||
return (0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
47
sys/dev/axgbe/xgbe_osdep.c
Normal file
47
sys/dev/axgbe/xgbe_osdep.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Contact Information :
|
||||
* Rajesh Kumar <rajesh1.kumar@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "xgbe.h"
|
||||
#include "xgbe_osdep.h"
|
||||
|
||||
/* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */
|
||||
uint32_t bitrev32(uint32_t x)
|
||||
{
|
||||
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
|
||||
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
|
||||
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
|
||||
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
|
||||
|
||||
return ((x >> 16) | (x << 16));
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2016,2017 SoftIron Inc.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* This software was developed by Andrew Turner under
|
||||
* the sponsorship of SoftIron Inc.
|
||||
@ -32,53 +34,175 @@
|
||||
#ifndef _XGBE_OSDEP_H_
|
||||
#define _XGBE_OSDEP_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/iflib.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
MALLOC_DECLARE(M_AXGBE);
|
||||
|
||||
typedef uint16_t __le16;
|
||||
typedef uint16_t __be16;
|
||||
typedef uint32_t __le32;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef struct {
|
||||
struct mtx lock;
|
||||
} spinlock_t;
|
||||
#define BIT(pos) (1ul << pos)
|
||||
|
||||
#define cpu_to_be16(x) be16toh(x)
|
||||
#define be16_to_cpu(x) htobe16(x)
|
||||
#define lower_32_bits(x) ((x) & 0xffffffffu)
|
||||
#define upper_32_bits(x) (((x) >> 32) & 0xffffffffu)
|
||||
#define cpu_to_le32(x) le32toh(x)
|
||||
#define le32_to_cpu(x) htole32(x)
|
||||
#define cpu_to_le16(x) htole16(x)
|
||||
|
||||
#define for_each_set_bit(bit, addr, size) \
|
||||
for ((bit) = find_first_bit((addr), (size)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
typedef struct mtx spinlock_t;
|
||||
|
||||
static inline void
|
||||
spin_lock_init(spinlock_t *spinlock)
|
||||
{
|
||||
|
||||
mtx_init(&spinlock->lock, "axgbe_spin", NULL, MTX_DEF);
|
||||
mtx_init(spinlock, "axgbe_spin", NULL, MTX_SPIN);
|
||||
}
|
||||
|
||||
#define spin_lock_irqsave(spinlock, flags) \
|
||||
do { \
|
||||
(flags) = intr_disable(); \
|
||||
mtx_lock(&(spinlock)->lock); \
|
||||
mtx_lock_spin(spinlock); \
|
||||
} while (0)
|
||||
|
||||
#define spin_unlock_irqrestore(spinlock, flags) \
|
||||
do { \
|
||||
mtx_unlock(&(spinlock)->lock); \
|
||||
mtx_unlock_spin(spinlock); \
|
||||
intr_restore(flags); \
|
||||
} while (0)
|
||||
|
||||
#define BIT(pos) (1ul << pos)
|
||||
#define ADVERTISED_Pause (1 << 0)
|
||||
#define ADVERTISED_Asym_Pause (1 << 1)
|
||||
#define ADVERTISED_Autoneg (1 << 2)
|
||||
#define ADVERTISED_Backplane (1 << 3)
|
||||
#define ADVERTISED_10000baseKR_Full (1 << 4)
|
||||
#define ADVERTISED_2500baseX_Full (1 << 5)
|
||||
#define ADVERTISED_1000baseKX_Full (1 << 6)
|
||||
#define ADVERTISED_100baseT_Full (1 << 7)
|
||||
#define ADVERTISED_10000baseR_FEC (1 << 8)
|
||||
#define ADVERTISED_10000baseT_Full (1 << 9)
|
||||
#define ADVERTISED_2500baseT_Full (1 << 10)
|
||||
#define ADVERTISED_1000baseT_Full (1 << 11)
|
||||
#define ADVERTISED_TP (1 << 12)
|
||||
#define ADVERTISED_FIBRE (1 << 13)
|
||||
#define ADVERTISED_1000baseX_Full (1 << 14)
|
||||
#define ADVERTISED_10000baseSR_Full (1 << 15)
|
||||
#define ADVERTISED_10000baseLR_Full (1 << 16)
|
||||
#define ADVERTISED_10000baseLRM_Full (1 << 17)
|
||||
#define ADVERTISED_10000baseER_Full (1 << 18)
|
||||
#define ADVERTISED_10000baseCR_Full (1 << 19)
|
||||
#define ADVERTISED_100baseT_Half (1 << 20)
|
||||
#define ADVERTISED_1000baseT_Half (1 << 21)
|
||||
|
||||
#define SUPPORTED_Pause (1 << 0)
|
||||
#define SUPPORTED_Asym_Pause (1 << 1)
|
||||
#define SUPPORTED_Autoneg (1 << 2)
|
||||
#define SUPPORTED_Backplane (1 << 3)
|
||||
#define SUPPORTED_10000baseKR_Full (1 << 4)
|
||||
#define SUPPORTED_2500baseX_Full (1 << 5)
|
||||
#define SUPPORTED_1000baseKX_Full (1 << 6)
|
||||
#define SUPPORTED_100baseT_Full (1 << 7)
|
||||
#define SUPPORTED_10000baseR_FEC (1 << 8)
|
||||
#define SUPPORTED_10000baseT_Full (1 << 9)
|
||||
#define SUPPORTED_2500baseT_Full (1 << 10)
|
||||
#define SUPPORTED_1000baseT_Full (1 << 11)
|
||||
#define SUPPORTED_TP (1 << 12)
|
||||
#define SUPPORTED_FIBRE (1 << 13)
|
||||
#define SUPPORTED_1000baseX_Full (1 << 14)
|
||||
#define SUPPORTED_10000baseSR_Full (1 << 15)
|
||||
#define SUPPORTED_10000baseLR_Full (1 << 16)
|
||||
#define SUPPORTED_10000baseLRM_Full (1 << 17)
|
||||
#define SUPPORTED_10000baseER_Full (1 << 18)
|
||||
#define SUPPORTED_10000baseCR_Full (1 << 19)
|
||||
#define SUPPORTED_100baseT_Half (1 << 20)
|
||||
#define SUPPORTED_1000baseT_Half (1 << 21)
|
||||
|
||||
#define LPA_PAUSE_ASYM 0x0800
|
||||
|
||||
#define AUTONEG_DISABLE 0
|
||||
#define AUTONEG_ENABLE 1
|
||||
|
||||
#define DUPLEX_UNKNOWN 1
|
||||
#define DUPLEX_FULL 2
|
||||
#define DUPLEX_HALF 3
|
||||
|
||||
#define SPEED_UNKNOWN 1
|
||||
#define SPEED_10000 2
|
||||
#define SPEED_2500 3
|
||||
#define SPEED_1000 4
|
||||
#define SPEED_100 5
|
||||
#define SPEED_10 6
|
||||
|
||||
#define BMCR_SPEED100 0x2000
|
||||
|
||||
#define MDIO_MMD_PMAPMD 1
|
||||
#define MDIO_MMD_PCS 3
|
||||
#define MDIO_MMD_AN 7
|
||||
#define MDIO_MMD_VEND1 30 /* Vendor specific 1 */
|
||||
#define MDIO_MMD_VEND2 31 /* Vendor specific 2 */
|
||||
|
||||
#define MDIO_PMA_10GBR_FECABLE 170
|
||||
#define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001
|
||||
#define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002
|
||||
#define MII_ADDR_C45 (1<<30)
|
||||
|
||||
#define MDIO_CTRL1 0x00 /* MII_BMCR */
|
||||
#define MDIO_CTRL1_RESET 0x8000 /* BMCR_RESET */
|
||||
#define MDIO_CTRL1_SPEEDSELEXT 0x2040 /* BMCR_SPEED1000|BMCR_SPEED100*/
|
||||
#define MDIO_CTRL1_SPEEDSEL (MDIO_CTRL1_SPEEDSELEXT | 0x3c)
|
||||
#define MDIO_AN_CTRL1_ENABLE 0x1000 /* BMCR_AUTOEN */
|
||||
#define MDIO_CTRL1_LPOWER 0x0800 /* BMCR_PDOWN */
|
||||
#define MDIO_AN_CTRL1_RESTART 0x0200 /* BMCR_STARTNEG */
|
||||
|
||||
#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00)
|
||||
|
||||
#define MDIO_STAT1 1 /* MII_BMSR */
|
||||
#define MDIO_STAT1_LSTATUS 0x0004 /* BMSR_LINK */
|
||||
|
||||
#define MDIO_DEVID1 2 /* MII_PHYSID1 */
|
||||
#define MDIO_DEVID2 3 /* MII_PHYSID2 */
|
||||
#define MDIO_SPEED 4
|
||||
#define MDIO_DEVS1 5
|
||||
#define MDIO_DEVS2 6
|
||||
#define MDIO_CTRL2 0x07
|
||||
#define MDIO_PCS_CTRL2_10GBR 0x0000
|
||||
#define MDIO_PCS_CTRL2_10GBX 0x0001
|
||||
#define MDIO_PCS_CTRL2_TYPE 0x0003
|
||||
|
||||
#define MDIO_AN_ADVERTISE 16
|
||||
|
||||
#define MDIO_AN_LPA 19
|
||||
|
||||
#define ETH_ALEN ETHER_ADDR_LEN
|
||||
#define ETH_HLEN ETHER_HDR_LEN
|
||||
#define ETH_FCS_LEN 4
|
||||
#define VLAN_HLEN ETHER_VLAN_ENCAP_LEN
|
||||
#define VLAN_NVID 4096
|
||||
#define VLAN_VID_MASK 0x0FFF
|
||||
|
||||
#define CRC32_POLY_LE 0xedb88320
|
||||
|
||||
#define ARRAY_SIZE(x) nitems(x)
|
||||
|
||||
#define BITS_PER_LONG (sizeof(long) * CHAR_BIT)
|
||||
#define BITS_TO_LONGS(n) howmany((n), BITS_PER_LONG)
|
||||
|
||||
#define BITMAP_LAST_WORD_MASK(n) (~0UL >> (BITS_PER_LONG - (n)))
|
||||
|
||||
#define min_t(t, a, b) MIN((t)(a), (t)(b))
|
||||
#define max_t(t, a, b) MAX((t)(a), (t)(b))
|
||||
|
||||
static inline void
|
||||
clear_bit(int pos, unsigned long *p)
|
||||
@ -103,86 +227,88 @@ set_bit(int pos, unsigned long *p)
|
||||
atomic_set_long(p, 1ul << pos);
|
||||
}
|
||||
|
||||
#define lower_32_bits(x) ((x) & 0xffffffffu)
|
||||
#define upper_32_bits(x) (((x) >> 32) & 0xffffffffu)
|
||||
#define cpu_to_le32(x) le32toh(x)
|
||||
#define le32_to_cpu(x) htole32(x)
|
||||
static inline int
|
||||
__ffsl(long mask)
|
||||
{
|
||||
|
||||
MALLOC_DECLARE(M_AXGBE);
|
||||
return (ffsl(mask) - 1);
|
||||
}
|
||||
|
||||
#define ADVERTISED_Pause 0x01
|
||||
#define ADVERTISED_Asym_Pause 0x02
|
||||
#define ADVERTISED_Autoneg 0x04
|
||||
#define ADVERTISED_Backplane 0x08
|
||||
#define ADVERTISED_10000baseKR_Full 0x10
|
||||
#define ADVERTISED_2500baseX_Full 0x20
|
||||
#define ADVERTISED_1000baseKX_Full 0x40
|
||||
static inline int
|
||||
fls64(uint64_t mask)
|
||||
{
|
||||
|
||||
#define AUTONEG_DISABLE 0
|
||||
#define AUTONEG_ENABLE 1
|
||||
return (flsll(mask));
|
||||
}
|
||||
|
||||
#define DUPLEX_UNKNOWN 1
|
||||
#define DUPLEX_FULL 2
|
||||
static inline int
|
||||
get_bitmask_order(unsigned int count)
|
||||
{
|
||||
int order;
|
||||
|
||||
#define SPEED_UNKNOWN 1
|
||||
#define SPEED_10000 2
|
||||
#define SPEED_2500 3
|
||||
#define SPEED_1000 4
|
||||
order = fls(count);
|
||||
return (order); /* We could be slightly more clever with -1 here... */
|
||||
}
|
||||
|
||||
#define SUPPORTED_Autoneg 0x01
|
||||
#define SUPPORTED_Pause 0x02
|
||||
#define SUPPORTED_Asym_Pause 0x04
|
||||
#define SUPPORTED_Backplane 0x08
|
||||
#define SUPPORTED_10000baseKR_Full 0x10
|
||||
#define SUPPORTED_1000baseKX_Full 0x20
|
||||
#define SUPPORTED_2500baseX_Full 0x40
|
||||
#define SUPPORTED_10000baseR_FEC 0x80
|
||||
static inline unsigned long
|
||||
find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
|
||||
{
|
||||
long mask;
|
||||
int offs;
|
||||
int bit;
|
||||
int pos;
|
||||
|
||||
#define BMCR_SPEED100 0x2000
|
||||
if (offset >= size)
|
||||
return (size);
|
||||
pos = offset / BITS_PER_LONG;
|
||||
offs = offset % BITS_PER_LONG;
|
||||
bit = BITS_PER_LONG * pos;
|
||||
addr += pos;
|
||||
if (offs) {
|
||||
mask = (*addr) & ~BITMAP_LAST_WORD_MASK(offs);
|
||||
if (mask)
|
||||
return (bit + __ffsl(mask));
|
||||
if (size - bit <= BITS_PER_LONG)
|
||||
return (size);
|
||||
bit += BITS_PER_LONG;
|
||||
addr++;
|
||||
}
|
||||
for (size -= bit; size >= BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG, bit += BITS_PER_LONG, addr++) {
|
||||
if (*addr == 0)
|
||||
continue;
|
||||
return (bit + __ffsl(*addr));
|
||||
}
|
||||
if (size) {
|
||||
mask = (*addr) & BITMAP_LAST_WORD_MASK(size);
|
||||
if (mask)
|
||||
bit += __ffsl(mask);
|
||||
else
|
||||
bit += size;
|
||||
}
|
||||
return (bit);
|
||||
}
|
||||
|
||||
#define MDIO_MMD_PMAPMD 1
|
||||
#define MDIO_MMD_PCS 3
|
||||
#define MDIO_MMD_AN 7
|
||||
#define MDIO_PMA_10GBR_FECABLE 170
|
||||
#define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001
|
||||
#define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002
|
||||
#define MII_ADDR_C45 (1<<30)
|
||||
static inline unsigned long
|
||||
find_first_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
long mask;
|
||||
int bit;
|
||||
|
||||
#define MDIO_CTRL1 0x00 /* MII_BMCR */
|
||||
#define MDIO_CTRL1_RESET 0x8000 /* BMCR_RESET */
|
||||
#define MDIO_CTRL1_SPEEDSELEXT 0x2040 /* BMCR_SPEED1000|BMCR_SPEED100*/
|
||||
#define MDIO_CTRL1_SPEEDSEL (MDIO_CTRL1_SPEEDSELEXT | 0x3c)
|
||||
#define MDIO_AN_CTRL1_ENABLE 0x1000 /* BMCR_AUTOEN */
|
||||
#define MDIO_CTRL1_LPOWER 0x0800 /* BMCR_PDOWN */
|
||||
#define MDIO_AN_CTRL1_RESTART 0x0200 /* BMCR_STARTNEG */
|
||||
|
||||
#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00)
|
||||
|
||||
#define MDIO_STAT1 1 /* MII_BMSR */
|
||||
#define MDIO_STAT1_LSTATUS 0x0004 /* BMSR_LINK */
|
||||
|
||||
#define MDIO_CTRL2 0x07
|
||||
#define MDIO_PCS_CTRL2_10GBR 0x0000
|
||||
#define MDIO_PCS_CTRL2_10GBX 0x0001
|
||||
#define MDIO_PCS_CTRL2_TYPE 0x0003
|
||||
|
||||
#define MDIO_AN_ADVERTISE 16
|
||||
|
||||
#define MDIO_AN_LPA 19
|
||||
|
||||
#define ETH_ALEN ETHER_ADDR_LEN
|
||||
#define ETH_HLEN ETHER_HDR_LEN
|
||||
#define ETH_FCS_LEN 4
|
||||
#define VLAN_HLEN ETHER_VLAN_ENCAP_LEN
|
||||
|
||||
#define ARRAY_SIZE(x) nitems(x)
|
||||
|
||||
#define BITS_PER_LONG (sizeof(long) * CHAR_BIT)
|
||||
#define BITS_TO_LONGS(n) howmany((n), BITS_PER_LONG)
|
||||
|
||||
#define NSEC_PER_SEC 1000000000ul
|
||||
|
||||
#define min_t(t, a, b) MIN((t)(a), (t)(b))
|
||||
#define max_t(t, a, b) MAX((t)(a), (t)(b))
|
||||
for (bit = 0; size >= BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG, bit += BITS_PER_LONG, addr++) {
|
||||
if (*addr == 0)
|
||||
continue;
|
||||
return (bit + __ffsl(*addr));
|
||||
}
|
||||
if (size) {
|
||||
mask = (*addr) & BITMAP_LAST_WORD_MASK(size);
|
||||
if (mask)
|
||||
bit += __ffsl(mask);
|
||||
else
|
||||
bit += size;
|
||||
}
|
||||
return (bit);
|
||||
}
|
||||
|
||||
#endif /* _XGBE_OSDEP_H_ */
|
||||
|
@ -58,6 +58,7 @@ SUBDIR= \
|
||||
ath_rate \
|
||||
ath_pci \
|
||||
${_autofs} \
|
||||
axgbe \
|
||||
backlight \
|
||||
${_bce} \
|
||||
${_bcm283x_clkman} \
|
||||
|
9
sys/modules/axgbe/Makefile
Normal file
9
sys/modules/axgbe/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "aarch64"
|
||||
SUBDIR= if_axa
|
||||
.elif ${MACHINE_CPUARCH} == "amd64"
|
||||
SUBDIR= if_axp
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
12
sys/modules/axgbe/if_axa/Makefile
Normal file
12
sys/modules/axgbe/if_axa/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
#$FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/axgbe
|
||||
|
||||
KMOD = if_axa
|
||||
SRCS = device_if.h bus_if.h miibus_if.h ofw_bus_if.h ifdi_if.h vnode_if.h
|
||||
SRCS += opt_inet.h opt_inet6.h opt_rss.h opt_iflib.h
|
||||
SRCS += if_axgbe.c xgbe-sysctl.c xgbe_osdep.c xgbe-desc.c xgbe-drv.c xgbe-mdio.c xgbe-dev.c xgbe-i2c.c xgbe-phy-v1.c xgbe-txrx.c
|
||||
|
||||
CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include
|
||||
|
||||
.include <bsd.kmod.mk>
|
12
sys/modules/axgbe/if_axp/Makefile
Normal file
12
sys/modules/axgbe/if_axp/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
#$FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/axgbe
|
||||
|
||||
KMOD = if_axp
|
||||
SRCS = device_if.h bus_if.h miibus_if.h pci_if.h ifdi_if.h vnode_if.h
|
||||
SRCS += opt_inet.h opt_inet6.h opt_rss.h opt_iflib.h
|
||||
SRCS += if_axgbe_pci.c xgbe-sysctl.c xgbe_osdep.c xgbe-desc.c xgbe-drv.c xgbe-mdio.c xgbe-dev.c xgbe-i2c.c xgbe-phy-v2.c xgbe-txrx.c
|
||||
|
||||
CFLAGS+= -I${SRCTOP}/sys/compat/linuxkpi/common/include
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user