Author: andrew
Date: Wed Feb 15 13:56:04 2017
New Revision: 313768
URL: https://svnweb.freebsd.org/changeset/base/313768

Log:
  Port the Linux AMX 10G network driver to FreeBSD as axgbe. It is unlikely
  we will import a newer version of the Linux code so the linuxkpi was not
  used.
  
  This is still missing 10G support, and multicast has not been tested.
  
  Reviewed by:  gnn
  Obtained from:        ABT Systems Ltd
  Sponsored by: SoftIron Inc
  Differential Revision:        https://reviews.freebsd.org/D8549

Added:
  head/sys/dev/axgbe/if_axgbe.c   (contents, props changed)
  head/sys/dev/axgbe/xgbe_osdep.h   (contents, props changed)
Modified:
  head/sys/arm64/conf/GENERIC
  head/sys/conf/files.arm64
  head/sys/dev/axgbe/xgbe-common.h   (contents, props changed)
  head/sys/dev/axgbe/xgbe-desc.c   (contents, props changed)
  head/sys/dev/axgbe/xgbe-dev.c   (contents, props changed)
  head/sys/dev/axgbe/xgbe-drv.c   (contents, props changed)
  head/sys/dev/axgbe/xgbe-mdio.c   (contents, props changed)
  head/sys/dev/axgbe/xgbe.h   (contents, props changed)

Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC Wed Feb 15 13:37:32 2017        (r313767)
+++ head/sys/arm64/conf/GENERIC Wed Feb 15 13:56:04 2017        (r313768)
@@ -119,6 +119,7 @@ options     PCI_IOV         # PCI SR-IOV support
 device         mii
 device         miibus          # MII bus support
 device         awg             # Allwinner EMAC Gigabit Ethernet
+device         axgbe           # AMD Opteron A1100 integrated NIC
 device         em              # Intel PRO/1000 Gigabit Ethernet Family
 device         ix              # Intel 10Gb Ethernet Family
 device         msk             # Marvell/SysKonnect Yukon II Gigabit Ethernet

Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64   Wed Feb 15 13:37:32 2017        (r313767)
+++ head/sys/conf/files.arm64   Wed Feb 15 13:56:04 2017        (r313768)
@@ -146,6 +146,11 @@ crypto/blowfish/bf_enc.c   optional        crypto
 crypto/des/des_enc.c           optional        crypto | ipsec | ipsec_support 
| netsmb
 dev/acpica/acpi_if.m           optional        acpi
 dev/ahci/ahci_generic.c                optional        ahci
+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/cpufreq/cpufreq_dt.c       optional        cpufreq fdt
 dev/hwpmc/hwpmc_arm64.c                optional        hwpmc
 dev/hwpmc/hwpmc_arm64_md.c     optional        hwpmc

Added: head/sys/dev/axgbe/if_axgbe.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/axgbe/if_axgbe.c       Wed Feb 15 13:56:04 2017        
(r313768)
@@ -0,0 +1,619 @@
+/*-
+ * Copyright (c) 2016,2017 SoftIron Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Andrew Turner under
+ * the sponsorship of SoftIron 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sx.h>
+#include <sys/taskqueue.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include "miibus_if.h"
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+static device_probe_t  axgbe_probe;
+static device_attach_t axgbe_attach;
+
+struct axgbe_softc {
+       /* Must be first */
+       struct xgbe_prv_data    prv;
+
+       uint8_t                 mac_addr[ETHER_ADDR_LEN];
+       struct ifmedia          media;
+};
+
+static struct ofw_compat_data compat_data[] = {
+       { "amd,xgbe-seattle-v1a",       true },
+       { NULL,                         false }
+};
+
+static struct resource_spec old_phy_spec[] = {
+       { SYS_RES_MEMORY,       0,      RF_ACTIVE }, /* Rx/Tx regs */
+       { SYS_RES_MEMORY,       1,      RF_ACTIVE }, /* Integration regs */
+       { SYS_RES_MEMORY,       2,      RF_ACTIVE }, /* Integration regs */
+       { SYS_RES_IRQ,          0,      RF_ACTIVE }, /* Interrupt */
+       { -1, 0 }
+};
+
+static struct resource_spec old_mac_spec[] = {
+       { SYS_RES_MEMORY,       0,      RF_ACTIVE }, /* MAC regs */
+       { SYS_RES_MEMORY,       1,      RF_ACTIVE }, /* PCS regs */
+       { SYS_RES_IRQ,          0,      RF_ACTIVE }, /* Device interrupt */
+       /* Per-channel interrupts */
+       { SYS_RES_IRQ,          1,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          2,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          3,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          4,      RF_ACTIVE | RF_OPTIONAL },
+       { -1, 0 }
+};
+
+static struct resource_spec mac_spec[] = {
+       { SYS_RES_MEMORY,       0,      RF_ACTIVE }, /* MAC regs */
+       { SYS_RES_MEMORY,       1,      RF_ACTIVE }, /* PCS regs */
+       { SYS_RES_MEMORY,       2,      RF_ACTIVE }, /* Rx/Tx regs */
+       { SYS_RES_MEMORY,       3,      RF_ACTIVE }, /* Integration regs */
+       { SYS_RES_MEMORY,       4,      RF_ACTIVE }, /* Integration regs */
+       { SYS_RES_IRQ,          0,      RF_ACTIVE }, /* Device interrupt */
+       /* Per-channel and auto-negotiation interrupts */
+       { SYS_RES_IRQ,          1,      RF_ACTIVE },
+       { SYS_RES_IRQ,          2,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          3,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          4,      RF_ACTIVE | RF_OPTIONAL },
+       { SYS_RES_IRQ,          5,      RF_ACTIVE | RF_OPTIONAL },
+       { -1, 0 }
+};
+
+MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data");
+
+static void
+axgbe_init(void *p)
+{
+       struct axgbe_softc *sc;
+       struct ifnet *ifp;
+
+       sc = p;
+       ifp = sc->prv.netdev;
+       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+               return;
+
+       ifp->if_drv_flags |= IFF_DRV_RUNNING;
+}
+
+static int
+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;
+
+       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);
+               break;
+       case SIOCSIFFLAGS:
+               error = 0;
+               break;
+       case SIOCSIFMEDIA:
+       case SIOCGIFMEDIA:
+               error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
+               break;
+       default:
+               error = ether_ioctl(ifp, command, data);
+               break;
+       }
+
+       return (error);
+}
+
+static void
+axgbe_qflush(struct ifnet *ifp)
+{
+
+       if_qflush(ifp);
+}
+
+static int
+axgbe_media_change(struct ifnet *ifp)
+{
+       struct axgbe_softc *sc;
+       int cur_media;
+
+       sc = ifp->if_softc;
+
+       sx_xlock(&sc->prv.an_mutex);
+       cur_media = sc->media.ifm_cur->ifm_media;
+
+       switch (IFM_SUBTYPE(cur_media)) {
+       case IFM_10G_KR:
+               sc->prv.phy.speed = SPEED_10000;
+               sc->prv.phy.autoneg = AUTONEG_DISABLE;
+               break;
+       case IFM_2500_KX:
+               sc->prv.phy.speed = SPEED_2500;
+               sc->prv.phy.autoneg = AUTONEG_DISABLE;
+               break;
+       case IFM_1000_KX:
+               sc->prv.phy.speed = SPEED_1000;
+               sc->prv.phy.autoneg = AUTONEG_DISABLE;
+               break;
+       case IFM_AUTO:
+               sc->prv.phy.autoneg = AUTONEG_ENABLE;
+               break;
+       }
+       sx_xunlock(&sc->prv.an_mutex);
+
+       return (-sc->prv.phy_if.phy_config_aneg(&sc->prv));
+}
+
+static void
+axgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+       struct axgbe_softc *sc;
+
+       sc = ifp->if_softc;
+
+       ifmr->ifm_status = IFM_AVALID;
+       if (!sc->prv.phy.link)
+               return;
+
+       ifmr->ifm_status |= IFM_ACTIVE;
+       ifmr->ifm_active = IFM_ETHER;
+
+       if (sc->prv.phy.duplex == DUPLEX_FULL)
+               ifmr->ifm_active |= IFM_FDX;
+       else
+               ifmr->ifm_active |= IFM_HDX;
+
+       switch (sc->prv.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;
+       }
+}
+
+static uint64_t
+axgbe_get_counter(struct ifnet *ifp, ift_counter c)
+{
+       struct xgbe_prv_data *pdata = ifp->if_softc;
+       struct xgbe_mmc_stats *pstats = &pdata->mmc_stats;
+
+       DBGPR("-->%s\n", __func__);
+
+       pdata->hw_if.read_mmc_stats(pdata);
+
+       switch(c) {
+       case IFCOUNTER_IPACKETS:
+               return (pstats->rxframecount_gb);
+       case IFCOUNTER_IERRORS:
+               return (pstats->rxframecount_gb -
+                   pstats->rxbroadcastframes_g -
+                   pstats->rxmulticastframes_g -
+                   pstats->rxunicastframes_g);
+       case IFCOUNTER_OPACKETS:
+               return (pstats->txframecount_gb);
+       case IFCOUNTER_OERRORS:
+               return (pstats->txframecount_gb - pstats->txframecount_g);
+       case IFCOUNTER_IBYTES:
+               return (pstats->rxoctetcount_gb);
+       case IFCOUNTER_OBYTES:
+               return (pstats->txoctetcount_gb);
+       default:
+               return (if_get_counter_default(ifp, c));
+       }
+}
+
+static int
+axgbe_probe(device_t dev)
+{
+
+       if (!ofw_bus_status_okay(dev))
+               return (ENXIO);
+
+       if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+               return (ENXIO);
+
+       device_set_desc(dev, "AMD 10 Gigabit Ethernet");
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+axgbe_get_optional_prop(device_t dev, phandle_t node, const char *name,
+    int *data, size_t len)
+{
+
+       if (!OF_hasprop(node, name))
+               return (-1);
+
+       if (OF_getencprop(node, name, data, len) <= 0) {
+               device_printf(dev,"%s property is invalid\n", name);
+               return (ENXIO);
+       }
+
+       return (0);
+}
+
+static int
+axgbe_attach(device_t dev)
+{
+       struct axgbe_softc *sc;
+       struct ifnet *ifp;
+       pcell_t phy_handle;
+       device_t phydev;
+       phandle_t node, phy_node;
+       struct resource *mac_res[11];
+       struct resource *phy_res[4];
+       ssize_t len;
+       int error, i, j;
+
+       sc = device_get_softc(dev);
+
+       node = ofw_bus_get_node(dev);
+       if (OF_getencprop(node, "phy-handle", &phy_handle,
+           sizeof(phy_handle)) <= 0) {
+               phy_node = node;
+
+               if (bus_alloc_resources(dev, mac_spec, mac_res)) {
+                       device_printf(dev,
+                           "could not allocate phy resources\n");
+                       return (ENXIO);
+               }
+
+               sc->prv.xgmac_res = mac_res[0];
+               sc->prv.xpcs_res = mac_res[1];
+               sc->prv.rxtx_res = mac_res[2];
+               sc->prv.sir0_res = mac_res[3];
+               sc->prv.sir1_res = mac_res[4];
+
+               sc->prv.dev_irq_res = mac_res[5];
+               sc->prv.per_channel_irq = OF_hasprop(node,
+                   XGBE_DMA_IRQS_PROPERTY);
+               for (i = 0, j = 6; j < nitems(mac_res) - 1 &&
+                   mac_res[j + 1] != NULL; i++, j++) {
+                       if (sc->prv.per_channel_irq) {
+                               sc->prv.chan_irq_res[i] = mac_res[j];
+                       }
+               }
+
+               /* The last entry is the auto-negotiation interrupt */
+               sc->prv.an_irq_res = mac_res[j];
+       } else {
+               phydev = OF_device_from_xref(phy_handle);
+               phy_node = ofw_bus_get_node(phydev);
+
+               if (bus_alloc_resources(phydev, old_phy_spec, phy_res)) {
+                       device_printf(dev,
+                           "could not allocate phy resources\n");
+                       return (ENXIO);
+               }
+
+               if (bus_alloc_resources(dev, old_mac_spec, mac_res)) {
+                       device_printf(dev,
+                           "could not allocate mac resources\n");
+                       return (ENXIO);
+               }
+
+               sc->prv.rxtx_res = phy_res[0];
+               sc->prv.sir0_res = phy_res[1];
+               sc->prv.sir1_res = phy_res[2];
+               sc->prv.an_irq_res = phy_res[3];
+
+               sc->prv.xgmac_res = mac_res[0];
+               sc->prv.xpcs_res = mac_res[1];
+               sc->prv.dev_irq_res = mac_res[2];
+               sc->prv.per_channel_irq = OF_hasprop(node,
+                   XGBE_DMA_IRQS_PROPERTY);
+               if (sc->prv.per_channel_irq) {
+                       for (i = 0, j = 3; i < nitems(sc->prv.chan_irq_res) &&
+                           mac_res[j] != NULL; i++, j++) {
+                               sc->prv.chan_irq_res[i] = mac_res[j];
+                       }
+               }
+       }
+
+       if ((len = OF_getproplen(node, "mac-address")) < 0) {
+               device_printf(dev, "No mac-address property\n");
+               return (EINVAL);
+       }
+
+       if (len != ETHER_ADDR_LEN)
+               return (EINVAL);
+
+       OF_getprop(node, "mac-address", sc->mac_addr, ETHER_ADDR_LEN);
+
+       sc->prv.netdev = ifp = if_alloc(IFT_ETHER);
+       if (ifp == NULL) {
+               device_printf(dev, "Cannot alloc ifnet\n");
+               return (ENXIO);
+       }
+
+       sc->prv.dev = dev;
+       sc->prv.dmat = bus_get_dma_tag(dev);
+       sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full |
+           ADVERTISED_1000baseKX_Full;
+
+
+       /*
+        * Read the needed properties from the phy node.
+        */
+
+       /* This is documented as optional, but Linux requires it */
+       if (OF_getencprop(phy_node, XGBE_SPEEDSET_PROPERTY, &sc->prv.speed_set,
+           sizeof(sc->prv.speed_set)) <= 0) {
+               device_printf(dev, "%s property is missing\n",
+                   XGBE_SPEEDSET_PROPERTY);
+               return (EINVAL);
+       }
+
+       error = axgbe_get_optional_prop(dev, phy_node, XGBE_BLWC_PROPERTY,
+           sc->prv.serdes_blwc, sizeof(sc->prv.serdes_blwc));
+       if (error > 0) {
+               return (error);
+       } else if (error < 0) {
+               sc->prv.serdes_blwc[0] = XGBE_SPEED_1000_BLWC;
+               sc->prv.serdes_blwc[1] = XGBE_SPEED_2500_BLWC;
+               sc->prv.serdes_blwc[2] = XGBE_SPEED_10000_BLWC;
+       }
+
+       error = axgbe_get_optional_prop(dev, phy_node, XGBE_CDR_RATE_PROPERTY,
+           sc->prv.serdes_cdr_rate, sizeof(sc->prv.serdes_cdr_rate));
+       if (error > 0) {
+               return (error);
+       } else if (error < 0) {
+               sc->prv.serdes_cdr_rate[0] = XGBE_SPEED_1000_CDR;
+               sc->prv.serdes_cdr_rate[1] = XGBE_SPEED_2500_CDR;
+               sc->prv.serdes_cdr_rate[2] = XGBE_SPEED_10000_CDR;
+       }
+
+       error = axgbe_get_optional_prop(dev, phy_node, XGBE_PQ_SKEW_PROPERTY,
+           sc->prv.serdes_pq_skew, sizeof(sc->prv.serdes_pq_skew));
+       if (error > 0) {
+               return (error);
+       } else if (error < 0) {
+               sc->prv.serdes_pq_skew[0] = XGBE_SPEED_1000_PQ;
+               sc->prv.serdes_pq_skew[1] = XGBE_SPEED_2500_PQ;
+               sc->prv.serdes_pq_skew[2] = XGBE_SPEED_10000_PQ;
+       }
+
+       error = axgbe_get_optional_prop(dev, phy_node, XGBE_TX_AMP_PROPERTY,
+           sc->prv.serdes_tx_amp, sizeof(sc->prv.serdes_tx_amp));
+       if (error > 0) {
+               return (error);
+       } else if (error < 0) {
+               sc->prv.serdes_tx_amp[0] = XGBE_SPEED_1000_TXAMP;
+               sc->prv.serdes_tx_amp[1] = XGBE_SPEED_2500_TXAMP;
+               sc->prv.serdes_tx_amp[2] = XGBE_SPEED_10000_TXAMP;
+       }
+
+       error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_CFG_PROPERTY,
+           sc->prv.serdes_dfe_tap_cfg, sizeof(sc->prv.serdes_dfe_tap_cfg));
+       if (error > 0) {
+               return (error);
+       } else if (error < 0) {
+               sc->prv.serdes_dfe_tap_cfg[0] = XGBE_SPEED_1000_DFE_TAP_CONFIG;
+               sc->prv.serdes_dfe_tap_cfg[1] = XGBE_SPEED_2500_DFE_TAP_CONFIG;
+               sc->prv.serdes_dfe_tap_cfg[2] = XGBE_SPEED_10000_DFE_TAP_CONFIG;
+       }
+
+       error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_ENA_PROPERTY,
+           sc->prv.serdes_dfe_tap_ena, sizeof(sc->prv.serdes_dfe_tap_ena));
+       if (error > 0) {
+               return (error);
+       } else if (error < 0) {
+               sc->prv.serdes_dfe_tap_ena[0] = XGBE_SPEED_1000_DFE_TAP_ENABLE;
+               sc->prv.serdes_dfe_tap_ena[1] = XGBE_SPEED_2500_DFE_TAP_ENABLE;
+               sc->prv.serdes_dfe_tap_ena[2] = XGBE_SPEED_10000_DFE_TAP_ENABLE;
+       }
+
+       /* 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;
+       } else {
+               sc->prv.axdomain = XGBE_DMA_SYS_AXDOMAIN;
+               sc->prv.arcache = XGBE_DMA_SYS_ARCACHE;
+               sc->prv.awcache = XGBE_DMA_SYS_AWCACHE;
+       }
+
+       /* Create the lock & workqueues */
+       spin_lock_init(&sc->prv.xpcs_lock);
+       sc->prv.dev_workqueue = taskqueue_create("axgbe", M_WAITOK,
+           taskqueue_thread_enqueue, &sc->prv.dev_workqueue);
+       taskqueue_start_threads(&sc->prv.dev_workqueue, 1, PI_NET,
+           "axgbe taskq");
+
+       /* Set the needed pointers */
+       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);
+
+       /* Reset the hardware */
+       sc->prv.hw_if.exit(&sc->prv);
+
+       /* Read the hardware features */
+       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.pause_autoneg = 1;
+       sc->prv.tx_pause = 1;
+       sc->prv.rx_pause = 1;
+       sc->prv.phy_speed = SPEED_UNKNOWN;
+       sc->prv.power_down = 0;
+
+       /* TODO: Limit to min(ncpus, hw rings) */
+       sc->prv.tx_ring_count = 1;
+       sc->prv.tx_q_count = 1;
+       sc->prv.rx_ring_count = 1;
+       sc->prv.rx_q_count = sc->prv.hw_feat.rx_q_cnt;
+
+       /* Init the PHY */
+       sc->prv.phy_if.phy_init(&sc->prv);
+
+       /* Set the coalescing */
+       xgbe_init_rx_coalesce(&sc->prv);
+       xgbe_init_tx_coalesce(&sc->prv);
+
+       if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+       ifp->if_init = axgbe_init;
+        ifp->if_softc = sc;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_ioctl = axgbe_ioctl;
+       ifp->if_transmit = xgbe_xmit;
+       ifp->if_qflush = axgbe_qflush;
+       ifp->if_get_counter = axgbe_get_counter;
+
+       /* TODO: Support HW offload */
+       ifp->if_capabilities = 0;
+       ifp->if_capenable = 0;
+       ifp->if_hwassist = 0;
+
+       ether_ifattach(ifp, sc->mac_addr);
+
+       ifmedia_init(&sc->media, IFM_IMASK, axgbe_media_change,
+           axgbe_media_status);
+#ifdef notyet
+       ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
+#endif
+       ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
+       ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+       ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
+
+       set_bit(XGBE_DOWN, &sc->prv.dev_state);
+
+       if (xgbe_open(ifp) < 0) {
+               device_printf(dev, "ndo_open failed\n");
+               return (ENXIO);
+       }
+
+       return (0);
+}
+
+static device_method_t axgbe_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         axgbe_probe),
+       DEVMETHOD(device_attach,        axgbe_attach),
+
+       { 0, 0 }
+};
+
+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);
+
+
+static struct ofw_compat_data phy_compat_data[] = {
+       { "amd,xgbe-phy-seattle-v1a",   true },
+       { NULL,                         false }
+};
+
+static int
+axgbephy_probe(device_t dev)
+{
+
+       if (!ofw_bus_status_okay(dev))
+               return (ENXIO);
+
+       if (!ofw_bus_search_compatible(dev, phy_compat_data)->ocd_data)
+               return (ENXIO);
+
+       device_set_desc(dev, "AMD 10 Gigabit Ethernet");
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+axgbephy_attach(device_t dev)
+{
+       phandle_t node;
+
+       node = ofw_bus_get_node(dev);
+       OF_device_register_xref(OF_xref_from_node(node), dev);
+
+       return (0);
+}
+
+static device_method_t axgbephy_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         axgbephy_probe),
+       DEVMETHOD(device_attach,        axgbephy_attach),
+
+       { 0, 0 }
+};
+
+static devclass_t axgbephy_devclass;
+
+DEFINE_CLASS_0(axgbephy, axgbephy_driver, axgbephy_methods, 0);
+EARLY_DRIVER_MODULE(axgbephy, simplebus, axgbephy_driver, axgbephy_devclass,
+    0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

Modified: head/sys/dev/axgbe/xgbe-common.h
==============================================================================
--- head/sys/dev/axgbe/xgbe-common.h    Wed Feb 15 13:37:32 2017        
(r313767)
+++ head/sys/dev/axgbe/xgbe-common.h    Wed Feb 15 13:56:04 2017        
(r313768)
@@ -112,11 +112,16 @@
  *     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.
+ *
+ * $FreeBSD$
  */
 
 #ifndef __XGBE_COMMON_H__
 #define __XGBE_COMMON_H__
 
+#include <sys/bus.h>
+#include <sys/rman.h>
+
 /* DMA register offsets */
 #define DMA_MR                         0x3000
 #define DMA_SBMR                       0x3004
@@ -1123,7 +1128,7 @@ do {                                                      
                \
  *  register definitions formed using the input names
  */
 #define XGMAC_IOREAD(_pdata, _reg)                                     \
-       ioread32((_pdata)->xgmac_regs + _reg)
+       bus_read_4((_pdata)->xgmac_res, _reg)
 
 #define XGMAC_IOREAD_BITS(_pdata, _reg, _field)                                
\
        GET_BITS(XGMAC_IOREAD((_pdata), _reg),                          \
@@ -1131,7 +1136,7 @@ do {                                                      
                \
                 _reg##_##_field##_WIDTH)
 
 #define XGMAC_IOWRITE(_pdata, _reg, _val)                              \
-       iowrite32((_val), (_pdata)->xgmac_regs + _reg)
+       bus_write_4((_pdata)->xgmac_res, _reg, (_val))
 
 #define XGMAC_IOWRITE_BITS(_pdata, _reg, _field, _val)                 \
 do {                                                                   \
@@ -1147,7 +1152,7 @@ do {                                                      
                \
  *  base register value is calculated by the queue or traffic class number
  */
 #define XGMAC_MTL_IOREAD(_pdata, _n, _reg)                             \
-       ioread32((_pdata)->xgmac_regs +                                 \
+       bus_read_4((_pdata)->xgmac_res,                                 \
                 MTL_Q_BASE + ((_n) * MTL_Q_INC) + _reg)
 
 #define XGMAC_MTL_IOREAD_BITS(_pdata, _n, _reg, _field)                        
\
@@ -1156,8 +1161,8 @@ do {                                                      
                \
                 _reg##_##_field##_WIDTH)
 
 #define XGMAC_MTL_IOWRITE(_pdata, _n, _reg, _val)                      \
-       iowrite32((_val), (_pdata)->xgmac_regs +                        \
-                 MTL_Q_BASE + ((_n) * MTL_Q_INC) + _reg)
+       bus_write_4((_pdata)->xgmac_res,                                \
+                 MTL_Q_BASE + ((_n) * MTL_Q_INC) + _reg, (_val))
 
 #define XGMAC_MTL_IOWRITE_BITS(_pdata, _n, _reg, _field, _val)         \
 do {                                                                   \
@@ -1173,7 +1178,7 @@ do {                                                      
                \
  *  base register value is obtained from the ring
  */
 #define XGMAC_DMA_IOREAD(_channel, _reg)                               \
-       ioread32((_channel)->dma_regs + _reg)
+       bus_space_read_4((_channel)->dma_tag, (_channel)->dma_handle, _reg)
 
 #define XGMAC_DMA_IOREAD_BITS(_channel, _reg, _field)                  \
        GET_BITS(XGMAC_DMA_IOREAD((_channel), _reg),                    \
@@ -1181,7 +1186,8 @@ do {                                                      
                \
                 _reg##_##_field##_WIDTH)
 
 #define XGMAC_DMA_IOWRITE(_channel, _reg, _val)                                
\
-       iowrite32((_val), (_channel)->dma_regs + _reg)
+       bus_space_write_4((_channel)->dma_tag, (_channel)->dma_handle,  \
+           _reg, (_val))
 
 #define XGMAC_DMA_IOWRITE_BITS(_channel, _reg, _field, _val)           \
 do {                                                                   \
@@ -1196,10 +1202,10 @@ do {                                                    
                \
  * within the register values of XPCS registers.
  */
 #define XPCS_IOWRITE(_pdata, _off, _val)                               \
-       iowrite32(_val, (_pdata)->xpcs_regs + (_off))
+       bus_write_4((_pdata)->xpcs_res, (_off), _val)
 
 #define XPCS_IOREAD(_pdata, _off)                                      \
-       ioread32((_pdata)->xpcs_regs + (_off))
+       bus_read_4((_pdata)->xpcs_res, (_off))
 
 /* Macros for building, reading or writing register values or bits
  * within the register values of SerDes integration registers.
@@ -1215,7 +1221,7 @@ do {                                                      
                \
                 _prefix##_##_field##_WIDTH, (_val))
 
 #define XSIR0_IOREAD(_pdata, _reg)                                     \
-       ioread16((_pdata)->sir0_regs + _reg)
+       bus_read_2((_pdata)->sir0_res, _reg)
 
 #define XSIR0_IOREAD_BITS(_pdata, _reg, _field)                                
\
        GET_BITS(XSIR0_IOREAD((_pdata), _reg),                          \
@@ -1223,7 +1229,7 @@ do {                                                      
                \
                 _reg##_##_field##_WIDTH)
 
 #define XSIR0_IOWRITE(_pdata, _reg, _val)                              \
-       iowrite16((_val), (_pdata)->sir0_regs + _reg)
+       bus_write_2((_pdata)->sir0_res, _reg, (_val))
 
 #define XSIR0_IOWRITE_BITS(_pdata, _reg, _field, _val)                 \
 do {                                                                   \
@@ -1235,7 +1241,7 @@ do {                                                      
                \
 } while (0)
 
 #define XSIR1_IOREAD(_pdata, _reg)                                     \
-       ioread16((_pdata)->sir1_regs + _reg)
+       bus_read_2((_pdata)->sir1_res, _reg)
 
 #define XSIR1_IOREAD_BITS(_pdata, _reg, _field)                                
\
        GET_BITS(XSIR1_IOREAD((_pdata), _reg),                          \
@@ -1243,7 +1249,7 @@ do {                                                      
                \
                 _reg##_##_field##_WIDTH)
 
 #define XSIR1_IOWRITE(_pdata, _reg, _val)                              \
-       iowrite16((_val), (_pdata)->sir1_regs + _reg)
+       bus_write_2((_pdata)->sir1_res, _reg, (_val))
 
 #define XSIR1_IOWRITE_BITS(_pdata, _reg, _field, _val)                 \
 do {                                                                   \
@@ -1258,7 +1264,7 @@ do {                                                      
                \
  * within the register values of SerDes RxTx registers.
  */
 #define XRXTX_IOREAD(_pdata, _reg)                                     \
-       ioread16((_pdata)->rxtx_regs + _reg)
+       bus_read_2((_pdata)->rxtx_res, _reg)
 
 #define XRXTX_IOREAD_BITS(_pdata, _reg, _field)                                
\
        GET_BITS(XRXTX_IOREAD((_pdata), _reg),                          \
@@ -1266,7 +1272,7 @@ do {                                                      
                \
                 _reg##_##_field##_WIDTH)
 
 #define XRXTX_IOWRITE(_pdata, _reg, _val)                              \
-       iowrite16((_val), (_pdata)->rxtx_regs + _reg)
+       bus_write_2((_pdata)->rxtx_res, _reg, (_val))
 
 #define XRXTX_IOWRITE_BITS(_pdata, _reg, _field, _val)                 \
 do {                                                                   \

Modified: head/sys/dev/axgbe/xgbe-desc.c
==============================================================================
--- head/sys/dev/axgbe/xgbe-desc.c      Wed Feb 15 13:37:32 2017        
(r313767)
+++ head/sys/dev/axgbe/xgbe-desc.c      Wed Feb 15 13:56:04 2017        
(r313768)
@@ -114,6 +114,9 @@
  *     THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include "xgbe.h"
 #include "xgbe-common.h"
 
@@ -128,45 +131,29 @@ static void xgbe_free_ring(struct xgbe_p
        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);
                }
 
-               kfree(ring->rdata);
+               free(ring->rdata, M_AXGBE);
                ring->rdata = NULL;
        }
 
-       if (ring->rx_hdr_pa.pages) {
-               dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma,
-                              ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE);
-               put_page(ring->rx_hdr_pa.pages);
-
-               ring->rx_hdr_pa.pages = NULL;
-               ring->rx_hdr_pa.pages_len = 0;
-               ring->rx_hdr_pa.pages_offset = 0;
-               ring->rx_hdr_pa.pages_dma = 0;
-       }
-
-       if (ring->rx_buf_pa.pages) {
-               dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma,
-                              ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE);
-               put_page(ring->rx_buf_pa.pages);
-
-               ring->rx_buf_pa.pages = NULL;
-               ring->rx_buf_pa.pages_len = 0;
-               ring->rx_buf_pa.pages_offset = 0;
-               ring->rx_buf_pa.pages_dma = 0;
-       }
-
-       if (ring->rdesc) {
-               dma_free_coherent(pdata->dev,
-                                 (sizeof(struct xgbe_ring_desc) *
-                                  ring->rdesc_count),
-                                 ring->rdesc, ring->rdesc_dma);
-               ring->rdesc = 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)
@@ -185,32 +172,71 @@ static void xgbe_free_ring_resources(str
        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;
-       ring->rdesc = dma_alloc_coherent(pdata->dev,
-                                        (sizeof(struct xgbe_ring_desc) *
-                                         rdesc_count), &ring->rdesc_dma,
-                                        GFP_KERNEL);
-       if (!ring->rdesc)
-               return -ENOMEM;
+       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 = kcalloc(rdesc_count, sizeof(struct xgbe_ring_data),
-                             GFP_KERNEL);
-       if (!ring->rdata)
-               return -ENOMEM;
-
-       netif_dbg(pdata, drv, pdata->netdev,
-                 "rdesc=%p, rdesc_dma=%pad, rdata=%p\n",
-                 ring->rdesc, &ring->rdesc_dma, ring->rdata);
+       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");
 
@@ -227,25 +253,17 @@ static int xgbe_alloc_ring_resources(str
 
        channel = pdata->channel;
        for (i = 0; i < pdata->channel_count; i++, channel++) {
-               netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n",
-                         channel->name);
-
                ret = xgbe_init_ring(pdata, channel->tx_ring,
                                     pdata->tx_desc_count);
                if (ret) {
-                       netdev_alert(pdata->netdev,
-                                    "error initializing Tx ring\n");
+                       printf("error initializing Tx ring\n");
                        goto err_ring;
                }
 
-               netif_dbg(pdata, drv, pdata->netdev, "%s - Rx ring:\n",
-                         channel->name);
-
                ret = xgbe_init_ring(pdata, channel->rx_ring,
                                     pdata->rx_desc_count);
                if (ret) {
-                       netdev_alert(pdata->netdev,
-                                    "error initializing Rx ring\n");
+                       printf("error initializing Rx ring\n");
                        goto err_ring;
                }
        }
@@ -260,93 +278,58 @@ err_ring:
        return ret;
 }
 
-static int xgbe_alloc_pages(struct xgbe_prv_data *pdata,
-                           struct xgbe_page_alloc *pa, gfp_t gfp, int order)
-{
-       struct page *pages = NULL;
-       dma_addr_t pages_dma;
-       int ret;
-
-       /* Try to obtain pages, decreasing order if necessary */
-       gfp |= __GFP_COLD | __GFP_COMP | __GFP_NOWARN;
-       while (order >= 0) {
-               pages = alloc_pages(gfp, order);
-               if (pages)
-                       break;
-
-               order--;
-       }
-       if (!pages)
-               return -ENOMEM;
-
-       /* Map the pages */
-       pages_dma = dma_map_page(pdata->dev, pages, 0,

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to