The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/axgbe/if_axgbe.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2016,2017 SoftIron Inc.
    5  * Copyright (c) 2020 Advanced Micro Devices, Inc.
    6  *
    7  * This software was developed by Andrew Turner under
    8  * the sponsorship of SoftIron Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/module.h>
   42 #include <sys/mutex.h>
   43 #include <sys/queue.h>
   44 #include <sys/rman.h>
   45 #include <sys/socket.h>
   46 #include <sys/sockio.h>
   47 #include <sys/sx.h>
   48 #include <sys/taskqueue.h>
   49 
   50 #include <net/ethernet.h>
   51 #include <net/if.h>
   52 #include <net/if_var.h>
   53 #include <net/if_media.h>
   54 #include <net/if_types.h>
   55 
   56 #include <dev/ofw/openfirm.h>
   57 #include <dev/ofw/ofw_bus.h>
   58 #include <dev/ofw/ofw_bus_subr.h>
   59 
   60 #include <machine/bus.h>
   61 
   62 #include "miibus_if.h"
   63 
   64 #include "xgbe.h"
   65 #include "xgbe-common.h"
   66 
   67 static device_probe_t   axgbe_probe;
   68 static device_attach_t  axgbe_attach;
   69 
   70 struct axgbe_softc {
   71         /* Must be first */
   72         struct xgbe_prv_data    prv;
   73 
   74         uint8_t                 mac_addr[ETHER_ADDR_LEN];
   75         struct ifmedia          media;
   76 };
   77 
   78 static struct ofw_compat_data compat_data[] = {
   79         { "amd,xgbe-seattle-v1a",       true },
   80         { NULL,                         false }
   81 };
   82 
   83 static struct resource_spec old_phy_spec[] = {
   84         { SYS_RES_MEMORY,       0,      RF_ACTIVE }, /* Rx/Tx regs */
   85         { SYS_RES_MEMORY,       1,      RF_ACTIVE }, /* Integration regs */
   86         { SYS_RES_MEMORY,       2,      RF_ACTIVE }, /* Integration regs */
   87         { SYS_RES_IRQ,          0,      RF_ACTIVE }, /* Interrupt */
   88         { -1, 0 }
   89 };
   90 
   91 static struct resource_spec old_mac_spec[] = {
   92         { SYS_RES_MEMORY,       0,      RF_ACTIVE }, /* MAC regs */
   93         { SYS_RES_MEMORY,       1,      RF_ACTIVE }, /* PCS regs */
   94         { SYS_RES_IRQ,          0,      RF_ACTIVE }, /* Device interrupt */
   95         /* Per-channel interrupts */
   96         { SYS_RES_IRQ,          1,      RF_ACTIVE | RF_OPTIONAL },
   97         { SYS_RES_IRQ,          2,      RF_ACTIVE | RF_OPTIONAL },
   98         { SYS_RES_IRQ,          3,      RF_ACTIVE | RF_OPTIONAL },
   99         { SYS_RES_IRQ,          4,      RF_ACTIVE | RF_OPTIONAL },
  100         { -1, 0 }
  101 };
  102 
  103 static struct resource_spec mac_spec[] = {
  104         { SYS_RES_MEMORY,       0,      RF_ACTIVE }, /* MAC regs */
  105         { SYS_RES_MEMORY,       1,      RF_ACTIVE }, /* PCS regs */
  106         { SYS_RES_MEMORY,       2,      RF_ACTIVE }, /* Rx/Tx regs */
  107         { SYS_RES_MEMORY,       3,      RF_ACTIVE }, /* Integration regs */
  108         { SYS_RES_MEMORY,       4,      RF_ACTIVE }, /* Integration regs */
  109         { SYS_RES_IRQ,          0,      RF_ACTIVE }, /* Device interrupt */
  110         /* Per-channel and auto-negotiation interrupts */
  111         { SYS_RES_IRQ,          1,      RF_ACTIVE },
  112         { SYS_RES_IRQ,          2,      RF_ACTIVE | RF_OPTIONAL },
  113         { SYS_RES_IRQ,          3,      RF_ACTIVE | RF_OPTIONAL },
  114         { SYS_RES_IRQ,          4,      RF_ACTIVE | RF_OPTIONAL },
  115         { SYS_RES_IRQ,          5,      RF_ACTIVE | RF_OPTIONAL },
  116         { -1, 0 }
  117 };
  118 
  119 static struct xgbe_version_data xgbe_v1 = {
  120         .init_function_ptrs_phy_impl    = xgbe_init_function_ptrs_phy_v1,
  121         .xpcs_access                    = XGBE_XPCS_ACCESS_V1,
  122         .tx_max_fifo_size               = 81920,
  123         .rx_max_fifo_size               = 81920,
  124         .tx_tstamp_workaround           = 1,
  125 };
  126 
  127 MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data");
  128 
  129 static void
  130 axgbe_init(void *p)
  131 {
  132         struct axgbe_softc *sc;
  133         if_t ifp;
  134 
  135         sc = p;
  136         ifp = sc->prv.netdev;
  137         if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
  138                 return;
  139 
  140         if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
  141 }
  142 
  143 static int
  144 axgbe_ioctl(if_t ifp, unsigned long command, caddr_t data)
  145 {
  146         struct axgbe_softc *sc = if_getsoftc(ifp);
  147         struct ifreq *ifr = (struct ifreq *)data;
  148         int error = 0;
  149 
  150         switch(command) {
  151         case SIOCSIFMTU:
  152                 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU_JUMBO)
  153                         error = EINVAL;
  154                 /* TODO - change it to iflib way */ 
  155                 break;
  156         case SIOCSIFFLAGS:
  157                 error = 0;
  158                 break;
  159         case SIOCSIFMEDIA:
  160         case SIOCGIFMEDIA:
  161                 error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
  162                 break;
  163         default:
  164                 error = ether_ioctl(ifp, command, data);
  165                 break;
  166         }
  167 
  168         return (error);
  169 }
  170 
  171 static void
  172 axgbe_qflush(if_t ifp)
  173 {
  174 
  175         if_qflush(ifp);
  176 }
  177 
  178 static int
  179 axgbe_media_change(if_t ifp)
  180 {
  181         struct axgbe_softc *sc;
  182         int cur_media;
  183 
  184         sc = if_getsoftc(ifp);
  185 
  186         sx_xlock(&sc->prv.an_mutex);
  187         cur_media = sc->media.ifm_cur->ifm_media;
  188 
  189         switch (IFM_SUBTYPE(cur_media)) {
  190         case IFM_10G_KR:
  191                 sc->prv.phy.speed = SPEED_10000;
  192                 sc->prv.phy.autoneg = AUTONEG_DISABLE;
  193                 break;
  194         case IFM_2500_KX:
  195                 sc->prv.phy.speed = SPEED_2500;
  196                 sc->prv.phy.autoneg = AUTONEG_DISABLE;
  197                 break;
  198         case IFM_1000_KX:
  199                 sc->prv.phy.speed = SPEED_1000;
  200                 sc->prv.phy.autoneg = AUTONEG_DISABLE;
  201                 break;
  202         case IFM_AUTO:
  203                 sc->prv.phy.autoneg = AUTONEG_ENABLE;
  204                 break;
  205         }
  206         sx_xunlock(&sc->prv.an_mutex);
  207 
  208         return (-sc->prv.phy_if.phy_config_aneg(&sc->prv));
  209 }
  210 
  211 static void
  212 axgbe_media_status(if_t ifp, struct ifmediareq *ifmr)
  213 {
  214         struct axgbe_softc *sc;
  215 
  216         sc = if_getsoftc(ifp);
  217 
  218         ifmr->ifm_status = IFM_AVALID;
  219         if (!sc->prv.phy.link)
  220                 return;
  221 
  222         ifmr->ifm_status |= IFM_ACTIVE;
  223         ifmr->ifm_active = IFM_ETHER;
  224 
  225         if (sc->prv.phy.duplex == DUPLEX_FULL)
  226                 ifmr->ifm_active |= IFM_FDX;
  227         else
  228                 ifmr->ifm_active |= IFM_HDX;
  229 
  230         switch (sc->prv.phy.speed) {
  231         case SPEED_10000:
  232                 ifmr->ifm_active |= IFM_10G_KR;
  233                 break;
  234         case SPEED_2500:
  235                 ifmr->ifm_active |= IFM_2500_KX;
  236                 break;
  237         case SPEED_1000:
  238                 ifmr->ifm_active |= IFM_1000_KX;
  239                 break;
  240         }
  241 }
  242 
  243 static uint64_t
  244 axgbe_get_counter(if_t ifp, ift_counter c)
  245 {
  246         struct xgbe_prv_data *pdata = if_getsoftc(ifp);
  247         struct xgbe_mmc_stats *pstats = &pdata->mmc_stats;
  248 
  249         DBGPR("-->%s\n", __func__);
  250 
  251         pdata->hw_if.read_mmc_stats(pdata);
  252 
  253         switch(c) {
  254         case IFCOUNTER_IPACKETS:
  255                 return (pstats->rxframecount_gb);
  256         case IFCOUNTER_IERRORS:
  257                 return (pstats->rxframecount_gb -
  258                     pstats->rxbroadcastframes_g -
  259                     pstats->rxmulticastframes_g -
  260                     pstats->rxunicastframes_g);
  261         case IFCOUNTER_OPACKETS:
  262                 return (pstats->txframecount_gb);
  263         case IFCOUNTER_OERRORS:
  264                 return (pstats->txframecount_gb - pstats->txframecount_g);
  265         case IFCOUNTER_IBYTES:
  266                 return (pstats->rxoctetcount_gb);
  267         case IFCOUNTER_OBYTES:
  268                 return (pstats->txoctetcount_gb);
  269         default:
  270                 return (if_get_counter_default(ifp, c));
  271         }
  272 }
  273 
  274 static int
  275 axgbe_probe(device_t dev)
  276 {
  277 
  278         if (!ofw_bus_status_okay(dev))
  279                 return (ENXIO);
  280 
  281         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
  282                 return (ENXIO);
  283 
  284         device_set_desc(dev, "AMD 10 Gigabit Ethernet");
  285         return (BUS_PROBE_DEFAULT);
  286 }
  287 
  288 static int
  289 axgbe_get_optional_prop(device_t dev, phandle_t node, const char *name,
  290     int *data, size_t len)
  291 {
  292 
  293         if (!OF_hasprop(node, name))
  294                 return (-1);
  295 
  296         if (OF_getencprop(node, name, data, len) <= 0) {
  297                 device_printf(dev,"%s property is invalid\n", name);
  298                 return (ENXIO);
  299         }
  300 
  301         return (0);
  302 }
  303 
  304 static int
  305 axgbe_attach(device_t dev)
  306 {
  307         struct axgbe_softc *sc;
  308         if_t ifp;
  309         pcell_t phy_handle;
  310         device_t phydev;
  311         phandle_t node, phy_node;
  312         struct resource *mac_res[11];
  313         struct resource *phy_res[4];
  314         ssize_t len;
  315         int error, i, j;
  316 
  317         sc = device_get_softc(dev);
  318 
  319         sc->prv.vdata = &xgbe_v1;
  320         node = ofw_bus_get_node(dev);
  321         if (OF_getencprop(node, "phy-handle", &phy_handle,
  322             sizeof(phy_handle)) <= 0) {
  323                 phy_node = node;
  324 
  325                 if (bus_alloc_resources(dev, mac_spec, mac_res)) {
  326                         device_printf(dev,
  327                             "could not allocate phy resources\n");
  328                         return (ENXIO);
  329                 }
  330 
  331                 sc->prv.xgmac_res = mac_res[0];
  332                 sc->prv.xpcs_res = mac_res[1];
  333                 sc->prv.rxtx_res = mac_res[2];
  334                 sc->prv.sir0_res = mac_res[3];
  335                 sc->prv.sir1_res = mac_res[4];
  336 
  337                 sc->prv.dev_irq_res = mac_res[5];
  338                 sc->prv.per_channel_irq = OF_hasprop(node,
  339                     XGBE_DMA_IRQS_PROPERTY);
  340                 for (i = 0, j = 6; j < nitems(mac_res) - 1 &&
  341                     mac_res[j + 1] != NULL; i++, j++) {
  342                         if (sc->prv.per_channel_irq) {
  343                                 sc->prv.chan_irq_res[i] = mac_res[j];
  344                         }
  345                 }
  346 
  347                 /* The last entry is the auto-negotiation interrupt */
  348                 sc->prv.an_irq_res = mac_res[j];
  349         } else {
  350                 phydev = OF_device_from_xref(phy_handle);
  351                 phy_node = ofw_bus_get_node(phydev);
  352 
  353                 if (bus_alloc_resources(phydev, old_phy_spec, phy_res)) {
  354                         device_printf(dev,
  355                             "could not allocate phy resources\n");
  356                         return (ENXIO);
  357                 }
  358 
  359                 if (bus_alloc_resources(dev, old_mac_spec, mac_res)) {
  360                         device_printf(dev,
  361                             "could not allocate mac resources\n");
  362                         return (ENXIO);
  363                 }
  364 
  365                 sc->prv.rxtx_res = phy_res[0];
  366                 sc->prv.sir0_res = phy_res[1];
  367                 sc->prv.sir1_res = phy_res[2];
  368                 sc->prv.an_irq_res = phy_res[3];
  369 
  370                 sc->prv.xgmac_res = mac_res[0];
  371                 sc->prv.xpcs_res = mac_res[1];
  372                 sc->prv.dev_irq_res = mac_res[2];
  373                 sc->prv.per_channel_irq = OF_hasprop(node,
  374                     XGBE_DMA_IRQS_PROPERTY);
  375                 if (sc->prv.per_channel_irq) {
  376                         for (i = 0, j = 3; i < nitems(sc->prv.chan_irq_res) &&
  377                             mac_res[j] != NULL; i++, j++) {
  378                                 sc->prv.chan_irq_res[i] = mac_res[j];
  379                         }
  380                 }
  381         }
  382 
  383         if ((len = OF_getproplen(node, "mac-address")) < 0) {
  384                 device_printf(dev, "No mac-address property\n");
  385                 return (EINVAL);
  386         }
  387 
  388         if (len != ETHER_ADDR_LEN)
  389                 return (EINVAL);
  390 
  391         OF_getprop(node, "mac-address", sc->mac_addr, ETHER_ADDR_LEN);
  392 
  393         sc->prv.netdev = ifp = if_alloc(IFT_ETHER);
  394         if (ifp == NULL) {
  395                 device_printf(dev, "Cannot alloc ifnet\n");
  396                 return (ENXIO);
  397         }
  398 
  399         sc->prv.dev = dev;
  400         sc->prv.dmat = bus_get_dma_tag(dev);
  401         sc->prv.phy.advertising = ADVERTISED_10000baseKR_Full |
  402             ADVERTISED_1000baseKX_Full;
  403 
  404 
  405         /*
  406          * Read the needed properties from the phy node.
  407          */
  408 
  409         /* This is documented as optional, but Linux requires it */
  410         if (OF_getencprop(phy_node, XGBE_SPEEDSET_PROPERTY, &sc->prv.speed_set,
  411             sizeof(sc->prv.speed_set)) <= 0) {
  412                 device_printf(dev, "%s property is missing\n",
  413                     XGBE_SPEEDSET_PROPERTY);
  414                 return (EINVAL);
  415         }
  416 
  417         error = axgbe_get_optional_prop(dev, phy_node, XGBE_BLWC_PROPERTY,
  418             sc->prv.serdes_blwc, sizeof(sc->prv.serdes_blwc));
  419         if (error > 0) {
  420                 return (error);
  421         } else if (error < 0) {
  422                 sc->prv.serdes_blwc[0] = XGBE_SPEED_1000_BLWC;
  423                 sc->prv.serdes_blwc[1] = XGBE_SPEED_2500_BLWC;
  424                 sc->prv.serdes_blwc[2] = XGBE_SPEED_10000_BLWC;
  425         }
  426 
  427         error = axgbe_get_optional_prop(dev, phy_node, XGBE_CDR_RATE_PROPERTY,
  428             sc->prv.serdes_cdr_rate, sizeof(sc->prv.serdes_cdr_rate));
  429         if (error > 0) {
  430                 return (error);
  431         } else if (error < 0) {
  432                 sc->prv.serdes_cdr_rate[0] = XGBE_SPEED_1000_CDR;
  433                 sc->prv.serdes_cdr_rate[1] = XGBE_SPEED_2500_CDR;
  434                 sc->prv.serdes_cdr_rate[2] = XGBE_SPEED_10000_CDR;
  435         }
  436 
  437         error = axgbe_get_optional_prop(dev, phy_node, XGBE_PQ_SKEW_PROPERTY,
  438             sc->prv.serdes_pq_skew, sizeof(sc->prv.serdes_pq_skew));
  439         if (error > 0) {
  440                 return (error);
  441         } else if (error < 0) {
  442                 sc->prv.serdes_pq_skew[0] = XGBE_SPEED_1000_PQ;
  443                 sc->prv.serdes_pq_skew[1] = XGBE_SPEED_2500_PQ;
  444                 sc->prv.serdes_pq_skew[2] = XGBE_SPEED_10000_PQ;
  445         }
  446 
  447         error = axgbe_get_optional_prop(dev, phy_node, XGBE_TX_AMP_PROPERTY,
  448             sc->prv.serdes_tx_amp, sizeof(sc->prv.serdes_tx_amp));
  449         if (error > 0) {
  450                 return (error);
  451         } else if (error < 0) {
  452                 sc->prv.serdes_tx_amp[0] = XGBE_SPEED_1000_TXAMP;
  453                 sc->prv.serdes_tx_amp[1] = XGBE_SPEED_2500_TXAMP;
  454                 sc->prv.serdes_tx_amp[2] = XGBE_SPEED_10000_TXAMP;
  455         }
  456 
  457         error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_CFG_PROPERTY,
  458             sc->prv.serdes_dfe_tap_cfg, sizeof(sc->prv.serdes_dfe_tap_cfg));
  459         if (error > 0) {
  460                 return (error);
  461         } else if (error < 0) {
  462                 sc->prv.serdes_dfe_tap_cfg[0] = XGBE_SPEED_1000_DFE_TAP_CONFIG;
  463                 sc->prv.serdes_dfe_tap_cfg[1] = XGBE_SPEED_2500_DFE_TAP_CONFIG;
  464                 sc->prv.serdes_dfe_tap_cfg[2] = XGBE_SPEED_10000_DFE_TAP_CONFIG;
  465         }
  466 
  467         error = axgbe_get_optional_prop(dev, phy_node, XGBE_DFE_ENA_PROPERTY,
  468             sc->prv.serdes_dfe_tap_ena, sizeof(sc->prv.serdes_dfe_tap_ena));
  469         if (error > 0) {
  470                 return (error);
  471         } else if (error < 0) {
  472                 sc->prv.serdes_dfe_tap_ena[0] = XGBE_SPEED_1000_DFE_TAP_ENABLE;
  473                 sc->prv.serdes_dfe_tap_ena[1] = XGBE_SPEED_2500_DFE_TAP_ENABLE;
  474                 sc->prv.serdes_dfe_tap_ena[2] = XGBE_SPEED_10000_DFE_TAP_ENABLE;
  475         }
  476 
  477         /* Check if the NIC is DMA coherent */
  478         sc->prv.coherent = OF_hasprop(node, "dma-coherent");
  479         if (sc->prv.coherent) {
  480                 sc->prv.arcr = XGBE_DMA_OS_ARCR;
  481                 sc->prv.awcr = XGBE_DMA_OS_AWCR;
  482         } else {
  483                 sc->prv.arcr = XGBE_DMA_SYS_ARCR;
  484                 sc->prv.awcr = XGBE_DMA_SYS_AWCR;
  485         }
  486 
  487         /* Create the lock & workqueues */
  488         spin_lock_init(&sc->prv.xpcs_lock);
  489         sc->prv.dev_workqueue = taskqueue_create("axgbe", M_WAITOK,
  490             taskqueue_thread_enqueue, &sc->prv.dev_workqueue);
  491         taskqueue_start_threads(&sc->prv.dev_workqueue, 1, PI_NET,
  492             "axgbe taskq");
  493 
  494         /* Set the needed pointers */
  495         xgbe_init_function_ptrs_phy(&sc->prv.phy_if);
  496         xgbe_init_function_ptrs_dev(&sc->prv.hw_if);
  497         xgbe_init_function_ptrs_desc(&sc->prv.desc_if);
  498         sc->prv.vdata->init_function_ptrs_phy_impl(&sc->prv.phy_if);
  499 
  500         /* Reset the hardware */
  501         sc->prv.hw_if.exit(&sc->prv);
  502 
  503         /* Read the hardware features */
  504         xgbe_get_all_hw_features(&sc->prv);
  505 
  506         /* Set default values */
  507         sc->prv.tx_desc_count = XGBE_TX_DESC_CNT;
  508         sc->prv.tx_sf_mode = MTL_TSF_ENABLE;
  509         sc->prv.tx_threshold = MTL_TX_THRESHOLD_64;
  510         sc->prv.tx_osp_mode = DMA_OSP_ENABLE;
  511         sc->prv.rx_desc_count = XGBE_RX_DESC_CNT;
  512         sc->prv.rx_sf_mode = MTL_RSF_DISABLE;
  513         sc->prv.rx_threshold = MTL_RX_THRESHOLD_64;
  514         sc->prv.pbl = DMA_PBL_128;
  515         sc->prv.pause_autoneg = 1;
  516         sc->prv.tx_pause = 1;
  517         sc->prv.rx_pause = 1;
  518         sc->prv.phy_speed = SPEED_UNKNOWN;
  519         sc->prv.power_down = 0;
  520 
  521         /* TODO: Limit to min(ncpus, hw rings) */
  522         sc->prv.tx_ring_count = 1;
  523         sc->prv.tx_q_count = 1;
  524         sc->prv.rx_ring_count = 1;
  525         sc->prv.rx_q_count = sc->prv.hw_feat.rx_q_cnt;
  526 
  527         /* Init the PHY */
  528         sc->prv.phy_if.phy_init(&sc->prv);
  529 
  530         /* Set the coalescing */
  531         xgbe_init_rx_coalesce(&sc->prv);
  532         xgbe_init_tx_coalesce(&sc->prv);
  533 
  534         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  535         if_setinitfn(ifp, axgbe_init);
  536         if_setsoftc(ifp, sc);
  537         if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
  538         if_setioctlfn(ifp, axgbe_ioctl);
  539         /* TODO - change it to iflib way */ 
  540         if_setqflushfn(ifp, axgbe_qflush);
  541         if_setgetcounterfn(ifp, axgbe_get_counter);
  542 
  543         /* TODO: Support HW offload */
  544         if_setcapabilities(ifp, 0);
  545         if_setcapenable(ifp, 0);
  546         if_sethwassist(ifp, 0);
  547 
  548         ether_ifattach(ifp, sc->mac_addr);
  549 
  550         ifmedia_init(&sc->media, IFM_IMASK, axgbe_media_change,
  551             axgbe_media_status);
  552 #ifdef notyet
  553         ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
  554 #endif
  555         ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
  556         ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
  557         ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
  558 
  559         set_bit(XGBE_DOWN, &sc->prv.dev_state);
  560 
  561         /* TODO - change it to iflib way */
  562         return (0);
  563 }
  564 
  565 static device_method_t axgbe_methods[] = {
  566         /* Device interface */
  567         DEVMETHOD(device_probe,         axgbe_probe),
  568         DEVMETHOD(device_attach,        axgbe_attach),
  569 
  570         { 0, 0 }
  571 };
  572 
  573 DEFINE_CLASS_0(axgbe, axgbe_driver, axgbe_methods,
  574     sizeof(struct axgbe_softc));
  575 DRIVER_MODULE(axa, simplebus, axgbe_driver, 0, 0);
  576 
  577 
  578 static struct ofw_compat_data phy_compat_data[] = {
  579         { "amd,xgbe-phy-seattle-v1a",   true },
  580         { NULL,                         false }
  581 };
  582 
  583 static int
  584 axgbephy_probe(device_t dev)
  585 {
  586 
  587         if (!ofw_bus_status_okay(dev))
  588                 return (ENXIO);
  589 
  590         if (!ofw_bus_search_compatible(dev, phy_compat_data)->ocd_data)
  591                 return (ENXIO);
  592 
  593         device_set_desc(dev, "AMD 10 Gigabit Ethernet");
  594         return (BUS_PROBE_DEFAULT);
  595 }
  596 
  597 static int
  598 axgbephy_attach(device_t dev)
  599 {
  600         phandle_t node;
  601 
  602         node = ofw_bus_get_node(dev);
  603         OF_device_register_xref(OF_xref_from_node(node), dev);
  604 
  605         return (0);
  606 }
  607 
  608 static device_method_t axgbephy_methods[] = {
  609         /* Device interface */
  610         DEVMETHOD(device_probe,         axgbephy_probe),
  611         DEVMETHOD(device_attach,        axgbephy_attach),
  612 
  613         { 0, 0 }
  614 };
  615 
  616 DEFINE_CLASS_0(axgbephy, axgbephy_driver, axgbephy_methods, 0);
  617 EARLY_DRIVER_MODULE(axgbephy, simplebus, axgbephy_driver,
  618     0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

Cache object: 995035df9a8a6466e440e929a25c7b81


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.